aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
authorWei Wang <wei.w.wang@intel.com>2019-03-12 17:34:40 +0800
committerMichael S. Tsirkin <mst@redhat.com>2019-03-12 21:22:31 -0400
commitae440bd14c002f3a5528bd38e8a285ea625c04ca (patch)
treef6103c72615030eea6d112800c775f9fda24a516 /hw/virtio
parent9d867123659ac32edd2a0b64cabe2dca544f1d0e (diff)
downloadqemu-ae440bd14c002f3a5528bd38e8a285ea625c04ca.zip
qemu-ae440bd14c002f3a5528bd38e8a285ea625c04ca.tar.gz
qemu-ae440bd14c002f3a5528bd38e8a285ea625c04ca.tar.bz2
virtio-balloon: fix a use-after-free case
The elem could theorically contain both outbuf and inbufs. We move the free operation to the end of this function to avoid using elem->in_sg while elem has been freed. Fixes: c13c4153f7 ("virtio-balloon: VIRTIO_BALLOON_F_FREE_PAGE_HINT") Reported-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Wei Wang <wei.w.wang@intel.com> CC: Michael S. Tsirkin <mst@redhat.com> CC: Dr. David Alan Gilbert <dgilbert@redhat.com> CC: Juan Quintela <quintela@redhat.com> CC: Peter Xu <peterx@redhat.com> Message-Id: <1552383280-4122-1-git-send-email-wei.w.wang@intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/virtio-balloon.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index e3a6594..b614552 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -391,6 +391,7 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
VirtQueueElement *elem;
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtQueue *vq = dev->free_page_vq;
+ bool ret = true;
while (dev->block_iothread) {
qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock);
@@ -405,13 +406,12 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
uint32_t id;
size_t size = iov_to_buf(elem->out_sg, elem->out_num, 0,
&id, sizeof(id));
- virtqueue_push(vq, elem, size);
- g_free(elem);
virtio_tswap32s(vdev, &id);
if (unlikely(size != sizeof(id))) {
virtio_error(vdev, "received an incorrect cmd id");
- return false;
+ ret = false;
+ goto out;
}
if (id == dev->free_page_report_cmd_id) {
dev->free_page_report_status = FREE_PAGE_REPORT_S_START;
@@ -431,11 +431,12 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
qemu_guest_free_page_hint(elem->in_sg[0].iov_base,
elem->in_sg[0].iov_len);
}
- virtqueue_push(vq, elem, 1);
- g_free(elem);
}
- return true;
+out:
+ virtqueue_push(vq, elem, 1);
+ g_free(elem);
+ return ret;
}
static void virtio_ballloon_get_free_page_hints(void *opaque)