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>
This commit is contained in:
parent
9d86712365
commit
ae440bd14c
|
@ -391,6 +391,7 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
|
||||||
VirtQueueElement *elem;
|
VirtQueueElement *elem;
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||||
VirtQueue *vq = dev->free_page_vq;
|
VirtQueue *vq = dev->free_page_vq;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
while (dev->block_iothread) {
|
while (dev->block_iothread) {
|
||||||
qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock);
|
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;
|
uint32_t id;
|
||||||
size_t size = iov_to_buf(elem->out_sg, elem->out_num, 0,
|
size_t size = iov_to_buf(elem->out_sg, elem->out_num, 0,
|
||||||
&id, sizeof(id));
|
&id, sizeof(id));
|
||||||
virtqueue_push(vq, elem, size);
|
|
||||||
g_free(elem);
|
|
||||||
|
|
||||||
virtio_tswap32s(vdev, &id);
|
virtio_tswap32s(vdev, &id);
|
||||||
if (unlikely(size != sizeof(id))) {
|
if (unlikely(size != sizeof(id))) {
|
||||||
virtio_error(vdev, "received an incorrect cmd id");
|
virtio_error(vdev, "received an incorrect cmd id");
|
||||||
return false;
|
ret = false;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (id == dev->free_page_report_cmd_id) {
|
if (id == dev->free_page_report_cmd_id) {
|
||||||
dev->free_page_report_status = FREE_PAGE_REPORT_S_START;
|
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,
|
qemu_guest_free_page_hint(elem->in_sg[0].iov_base,
|
||||||
elem->in_sg[0].iov_len);
|
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)
|
static void virtio_ballloon_get_free_page_hints(void *opaque)
|
||||||
|
|
Loading…
Reference in a new issue