|
|
76daa3 |
From 43003baf954053a0857535220292294512c8ada2 Mon Sep 17 00:00:00 2001
|
|
|
76daa3 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
76daa3 |
Date: Mon, 12 Jun 2017 13:03:41 +0200
|
|
|
76daa3 |
Subject: [PATCH 05/13] commit: Fix use after free in completion
|
|
|
76daa3 |
|
|
|
76daa3 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
76daa3 |
Message-id: <1497272622-32221-2-git-send-email-kwolf@redhat.com>
|
|
|
76daa3 |
Patchwork-id: 75583
|
|
|
76daa3 |
O-Subject: [RHEL-7.4 qemu-kvm-rhev PATCH 1/2] commit: Fix use after free in completion
|
|
|
76daa3 |
Bugzilla: 1452048
|
|
|
76daa3 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
76daa3 |
|
|
|
76daa3 |
The final bdrv_set_backing_hd() could be working on already freed nodes
|
|
|
76daa3 |
because the commit job drops its references (through BlockBackends) to
|
|
|
76daa3 |
both overlay_bs and top already a bit earlier.
|
|
|
76daa3 |
|
|
|
76daa3 |
One way to trigger the bug is hot unplugging a disk for which
|
|
|
76daa3 |
blockdev_mark_auto_del() cancels the block job.
|
|
|
76daa3 |
|
|
|
76daa3 |
Fix this by taking BDS-level references while we're still using the
|
|
|
76daa3 |
nodes.
|
|
|
76daa3 |
|
|
|
76daa3 |
Cc: qemu-stable@nongnu.org
|
|
|
76daa3 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
76daa3 |
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
|
76daa3 |
(cherry picked from commit 19ebd13ed45ad5d5f277f5914d55b83f13eb09eb)
|
|
|
76daa3 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
76daa3 |
---
|
|
|
76daa3 |
block/commit.c | 7 +++++++
|
|
|
76daa3 |
1 file changed, 7 insertions(+)
|
|
|
76daa3 |
|
|
|
76daa3 |
diff --git a/block/commit.c b/block/commit.c
|
|
|
76daa3 |
index 76a0d98..3bae46e 100644
|
|
|
76daa3 |
--- a/block/commit.c
|
|
|
76daa3 |
+++ b/block/commit.c
|
|
|
76daa3 |
@@ -89,6 +89,10 @@ static void commit_complete(BlockJob *job, void *opaque)
|
|
|
76daa3 |
int ret = data->ret;
|
|
|
76daa3 |
bool remove_commit_top_bs = false;
|
|
|
76daa3 |
|
|
|
76daa3 |
+ /* Make sure overlay_bs and top stay around until bdrv_set_backing_hd() */
|
|
|
76daa3 |
+ bdrv_ref(top);
|
|
|
76daa3 |
+ bdrv_ref(overlay_bs);
|
|
|
76daa3 |
+
|
|
|
76daa3 |
/* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before
|
|
|
76daa3 |
* the normal backing chain can be restored. */
|
|
|
76daa3 |
blk_unref(s->base);
|
|
|
76daa3 |
@@ -124,6 +128,9 @@ static void commit_complete(BlockJob *job, void *opaque)
|
|
|
76daa3 |
if (remove_commit_top_bs) {
|
|
|
76daa3 |
bdrv_set_backing_hd(overlay_bs, top, &error_abort);
|
|
|
76daa3 |
}
|
|
|
76daa3 |
+
|
|
|
76daa3 |
+ bdrv_unref(overlay_bs);
|
|
|
76daa3 |
+ bdrv_unref(top);
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
static void coroutine_fn commit_run(void *opaque)
|
|
|
76daa3 |
--
|
|
|
76daa3 |
1.8.3.1
|
|
|
76daa3 |
|