diff options
author | Wei Wang <wei.w.wang@intel.com> | 2019-03-12 17:34:40 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2019-03-12 21:22:31 -0400 |
commit | ae440bd14c002f3a5528bd38e8a285ea625c04ca (patch) | |
tree | f6103c72615030eea6d112800c775f9fda24a516 /hw/virtio/virtio-balloon.c | |
parent | 9d867123659ac32edd2a0b64cabe2dca544f1d0e (diff) | |
download | qemu-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/virtio-balloon.c')
-rw-r--r-- | hw/virtio/virtio-balloon.c | 13 |
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) |