From: Kevin Wolf Date: Fri, 2 Jun 2017 21:04:55 +0000 (+0200) Subject: commit: Fix use after free in completion X-Git-Tag: v2.9.1~53 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;ds=sidebyside;h=f28b8906dd38816ed4da5a98bdeb5ff797afae8a;p=mirror_qemu.git commit: Fix use after free in completion The final bdrv_set_backing_hd() could be working on already freed nodes because the commit job drops its references (through BlockBackends) to both overlay_bs and top already a bit earlier. One way to trigger the bug is hot unplugging a disk for which blockdev_mark_auto_del() cancels the block job. Fix this by taking BDS-level references while we're still using the nodes. Cc: qemu-stable@nongnu.org Signed-off-by: Kevin Wolf Reviewed-by: John Snow (cherry picked from commit 19ebd13ed45ad5d5f277f5914d55b83f13eb09eb) Signed-off-by: Michael Roth --- diff --git a/block/commit.c b/block/commit.c index 76a0d98c6f..3bae46e9dd 100644 --- a/block/commit.c +++ b/block/commit.c @@ -89,6 +89,10 @@ static void commit_complete(BlockJob *job, void *opaque) int ret = data->ret; bool remove_commit_top_bs = false; + /* Make sure overlay_bs and top stay around until bdrv_set_backing_hd() */ + bdrv_ref(top); + bdrv_ref(overlay_bs); + /* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before * the normal backing chain can be restored. */ blk_unref(s->base); @@ -124,6 +128,9 @@ static void commit_complete(BlockJob *job, void *opaque) if (remove_commit_top_bs) { bdrv_set_backing_hd(overlay_bs, top, &error_abort); } + + bdrv_unref(overlay_bs); + bdrv_unref(top); } static void coroutine_fn commit_run(void *opaque)