aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorLi Qiang <liq3ea@163.com>2020-09-19 01:27:06 -0700
committerMichael S. Tsirkin <mst@redhat.com>2020-09-29 02:15:24 -0400
commit2d69eba5fe52045b2c8b0d04fd3806414352afc1 (patch)
tree6790a25a6d1fca04016cd6455d5710a59b3e5b8a /hw
parenta6704a34cf02add13964149e0de6453ae62bd9db (diff)
downloadqemu-2d69eba5fe52045b2c8b0d04fd3806414352afc1.zip
qemu-2d69eba5fe52045b2c8b0d04fd3806414352afc1.tar.gz
qemu-2d69eba5fe52045b2c8b0d04fd3806414352afc1.tar.bz2
virtio: update MemoryRegionCaches when guest set bad features
Current the 'virtio_set_features' only update the 'MemorRegionCaches' when the 'virtio_set_features_nocheck' return '0' which means it is not bad features. However the guest can still trigger the access of the used vring after set bad features. In this situation it will cause assert failure in 'ADDRESS_SPACE_ST_CACHED'. Buglink: https://bugs.launchpad.net/qemu/+bug/1890333 Fixes: db812c4073c7 ("virtio: update MemoryRegionCaches when guest negotiates features") Reported-by: Alexander Bulekov <alxndr@bu.edu> Signed-off-by: Li Qiang <liq3ea@163.com> Message-Id: <20200919082706.6703-1-liq3ea@163.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/virtio/virtio.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index a2edb4f..6f8f865 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2963,17 +2963,16 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val)
return -EINVAL;
}
ret = virtio_set_features_nocheck(vdev, val);
- if (!ret) {
- if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
- /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */
- int i;
- for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
- if (vdev->vq[i].vring.num != 0) {
- virtio_init_region_cache(vdev, i);
- }
+ if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */
+ int i;
+ for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
+ if (vdev->vq[i].vring.num != 0) {
+ virtio_init_region_cache(vdev, i);
}
}
-
+ }
+ if (!ret) {
if (!virtio_device_started(vdev, vdev->status) &&
!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
vdev->start_on_kick = true;