Per the virtio spec [*] the vring is aligned, so the 'flag' field
is also 16-bit aligned. If it is not, this is a guest error, and
we'd rather report any malicious activity.
Enforce the transaction alignment by setting the 'aligned' attribute
and log unaligned addresses.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/virtio/virtio.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 1b8bc194ce1..f19d12fc71e 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -291,15 +291,24 @@ static inline bool vring_avail_flags(VirtQueue *vq, uint16_t *val)
{
VRingMemoryRegionCaches *caches = vring_get_region_caches(vq);
hwaddr pa = offsetof(VRingAvail, flags);
+ MemTxAttrs attrs = { .aligned = 1 };
+ MemTxResult res;
if (!caches) {
*val = 0;
return true;
}
- *val = virtio_lduw_phys_cached_with_attrs(vq->vdev, &caches->avail, pa);
+ *val = virtio_lduw_phys_cached_with_attrs(vq->vdev, &caches->avail,
+ pa, attrs, &res);
+ if (res == MEMTX_UNALIGNED_ERROR) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "virtio: vring flag address 0x%" HWADDR_PRIX " "
+ "is not aligned\n", pa);
+ return false;
+ }
- return true;
+ return res == MEMTX_OK;
}
/* Called within rcu_read_lock(). */
--
2.26.3