All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 04/10] block/mirror: Fix use-after-free
Date: Fri,  7 Apr 2017 15:47:39 +0200	[thread overview]
Message-ID: <1491572865-8549-5-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1491572865-8549-1-git-send-email-kwolf@redhat.com>

From: Max Reitz <mreitz@redhat.com>

If @bs does not have any parents, the only reference to @mirror_top_bs
will be held by the BlockJob object after the bdrv_unref() following
block_job_create(). However, if block_job_create() fails, this reference
will not exist and @mirror_top_bs will have been deleted when we
goto fail.

The issue comes back at all later entries to the fail label: We delete
the BlockJob object before rolling back our changes to the node graph.
This means that we will delete @mirror_top_bs in the process.

All in all, whenever @bs does not have any parents and we go down the
fail path we will dereference @mirror_top_bs after it has been deleted.

Fix this by invoking bdrv_unref() only when block_job_create() was
successful and by bdrv_ref()'ing @mirror_top_bs in the fail path before
deleting the BlockJob object. Finally, bdrv_unref() it at the end of the
fail path after we actually no longer need it.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/mirror.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 9e2fecc..46ecd38 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1150,7 +1150,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
     mirror_top_bs->total_sectors = bs->total_sectors;
 
     /* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
-     * it alive until block_job_create() even if bs has no parent. */
+     * it alive until block_job_create() succeeds even if bs has no parent. */
     bdrv_ref(mirror_top_bs);
     bdrv_drained_begin(bs);
     bdrv_append(mirror_top_bs, bs, &local_err);
@@ -1168,10 +1168,12 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
                          BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
                          BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD, speed,
                          creation_flags, cb, opaque, errp);
-    bdrv_unref(mirror_top_bs);
     if (!s) {
         goto fail;
     }
+    /* The block job now has a reference to this node */
+    bdrv_unref(mirror_top_bs);
+
     s->source = bs;
     s->mirror_top_bs = mirror_top_bs;
 
@@ -1242,6 +1244,10 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
 
 fail:
     if (s) {
+        /* Make sure this BDS does not go away until we have completed the graph
+         * changes below */
+        bdrv_ref(mirror_top_bs);
+
         g_free(s->replaces);
         blk_unref(s->target);
         block_job_unref(&s->common);
@@ -1250,6 +1256,8 @@ fail:
     bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
                             &error_abort);
     bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
+
+    bdrv_unref(mirror_top_bs);
 }
 
 void mirror_start(const char *job_id, BlockDriverState *bs,
-- 
1.8.3.1

  parent reply	other threads:[~2017-04-07 13:48 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-07 13:47 [Qemu-devel] [PULL 00/10] Block layer fixes for 2.9.0-rc4 Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 01/10] block: Ignore guest dev permissions during incoming migration Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 02/10] commit: Set commit_top_bs->aio_context Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 03/10] commit: Set commit_top_bs->total_sectors Kevin Wolf
2017-04-07 13:47 ` Kevin Wolf [this message]
2017-04-07 13:47 ` [Qemu-devel] [PULL 05/10] iotests: Add mirror tests for orphaned source Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 06/10] qemu-img: img_create does not support image-opts, fix docs Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 07/10] block: Don't check permissions for copy on read Kevin Wolf
2017-04-07 14:11   ` Eric Blake
2017-04-07 13:47 ` [Qemu-devel] [PULL 08/10] block: Fix unpaired aio_disable_external in external snapshot Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 09/10] block: Assert attached child node has right aio context Kevin Wolf
2017-04-07 13:47 ` [Qemu-devel] [PULL 10/10] mirror: Fix aio context of mirror_top_bs Kevin Wolf
2017-04-07 15:24 ` [Qemu-devel] [PULL 00/10] Block layer fixes for 2.9.0-rc4 Peter Maydell
2017-04-12 23:51 ` no-reply
2017-04-13  0:00   ` Fam Zheng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1491572865-8549-5-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.