diff options
author | Dave Voutila <dv@cvs.openbsd.org> | 2021-08-29 18:01:33 +0000 |
---|---|---|
committer | Dave Voutila <dv@cvs.openbsd.org> | 2021-08-29 18:01:33 +0000 |
commit | 6651663513278a2d0c31b8a1b9816a43d473a752 (patch) | |
tree | 3f372dcf6f051bd43d24f411140af488e834c406 /usr.sbin/vmd | |
parent | 71f8dd0ebb3fbc6b61c9e90e7897afb714a1acc6 (diff) |
Mask viornd descriptor value to prevent out of bound reads.
viornd did not mask the descriptor value in the avialable ring
allowing guest values to read past the end of the descriptor table.
While here, change fatal to fatalx because errno is not set.
Reported by Ilja van Sprundel
ok mlarkin@
Diffstat (limited to 'usr.sbin/vmd')
-rw-r--r-- | usr.sbin/vmd/virtio.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c index b45f42ba19e..c1739b9bbbf 100644 --- a/usr.sbin/vmd/virtio.c +++ b/usr.sbin/vmd/virtio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.c,v 1.96 2021/08/29 12:17:38 dv Exp $ */ +/* $OpenBSD: virtio.c,v 1.97 2021/08/29 18:01:32 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -151,7 +151,7 @@ viornd_notifyq(void) uint64_t q_gpa; uint32_t vr_sz; size_t sz; - int ret; + int dxx, ret; uint16_t aidx, uidx; char *buf, *rnd_data; struct vring_desc *desc; @@ -188,26 +188,27 @@ viornd_notifyq(void) aidx = avail->idx & VIORND_QUEUE_MASK; uidx = used->idx & VIORND_QUEUE_MASK; - sz = desc[avail->ring[aidx]].len; + dxx = avail->ring[aidx] & VIORND_QUEUE_MASK; + + sz = desc[dxx].len; if (sz > MAXPHYS) - fatal("viornd descriptor size too large (%zu)", sz); + fatalx("viornd descriptor size too large (%zu)", sz); rnd_data = malloc(sz); if (rnd_data != NULL) { - arc4random_buf(rnd_data, desc[avail->ring[aidx]].len); - if (write_mem(desc[avail->ring[aidx]].addr, rnd_data, sz)) { + arc4random_buf(rnd_data, sz); + if (write_mem(desc[dxx].addr, rnd_data, sz)) { log_warnx("viornd: can't write random data @ " "0x%llx", - desc[avail->ring[aidx]].addr); + desc[dxx].addr); } else { /* ret == 1 -> interrupt needed */ /* XXX check VIRTIO_F_NO_INTR */ ret = 1; viornd.cfg.isr_status = 1; - used->ring[uidx].id = avail->ring[aidx] & - VIORND_QUEUE_MASK; - used->ring[uidx].len = desc[avail->ring[aidx]].len; + used->ring[uidx].id = dxx; + used->ring[uidx].len = sz; used->idx++; if (write_mem(q_gpa, buf, vr_sz)) { |