qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org
Subject: [PULL 01/50] crypto: perform permission checks under BQL
Date: Fri,  4 Mar 2022 17:46:22 +0100	[thread overview]
Message-ID: <20220304164711.474713-2-kwolf@redhat.com> (raw)
In-Reply-To: <20220304164711.474713-1-kwolf@redhat.com>

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

Move the permission API calls into driver-specific callbacks
that always run under BQL. In this case, bdrv_crypto_luks
needs to perform permission checks before and after
qcrypto_block_amend_options(). The problem is that the caller,
block_crypto_amend_options_generic_luks(), can also run in I/O
from .bdrv_co_amend(). This does not comply with Global State-I/O API split,
as permissions API must always run under BQL.

Firstly, introduce .bdrv_amend_pre_run() and .bdrv_amend_clean()
callbacks. These two callbacks are guaranteed to be invoked under
BQL, respectively before and after .bdrv_co_amend().
They take care of performing the permission checks
in the same way as they are currently done before and after
qcrypto_block_amend_options().
These callbacks are in preparation for next patch, where we
delete the original permission check. Right now they just add redundant
control.

Then, call .bdrv_amend_pre_run() before job_start in
qmp_x_blockdev_amend(), so that it will be run before the job coroutine
is created and stay in the main loop.
As a cleanup, use JobDriver's .clean() callback to call
.bdrv_amend_clean(), and run amend-specific cleanup callbacks under BQL.

After this patch, permission failures occur early in the blockdev-amend
job to update a LUKS volume's keys.  iotest 296 must now expect them in
x-blockdev-amend's QMP reply instead of waiting for the actual job to
fail later.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Message-Id: <20220209105452.1694545-2-eesposit@redhat.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220304153729.711387-6-hreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block_int.h  | 14 ++++++++++++++
 block/amend.c              | 25 +++++++++++++++++++++++++
 block/crypto.c             | 33 +++++++++++++++++++++++++++++++++
 tests/qemu-iotests/296     |  8 ++++++--
 tests/qemu-iotests/296.out | 17 +++++------------
 5 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/include/block/block_int.h b/include/block/block_int.h
index 27008cfb22..31bd788919 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -124,6 +124,20 @@ struct BlockDriver {
      * on those children.
      */
     bool is_format;
+
+    /*
+     * This function is invoked under BQL before .bdrv_co_amend()
+     * (which in contrast does not necessarily run under the BQL)
+     * to allow driver-specific initialization code that requires
+     * the BQL, like setting up specific permission flags.
+     */
+    int (*bdrv_amend_pre_run)(BlockDriverState *bs, Error **errp);
+    /*
+     * This function is invoked under BQL after .bdrv_co_amend()
+     * to allow cleaning up what was done in .bdrv_amend_pre_run().
+     */
+    void (*bdrv_amend_clean)(BlockDriverState *bs);
+
     /*
      * Return true if @to_replace can be replaced by a BDS with the
      * same data as @bs without it affecting @bs's behavior (that is,
diff --git a/block/amend.c b/block/amend.c
index 392df9ef83..f465738665 100644
--- a/block/amend.c
+++ b/block/amend.c
@@ -53,10 +53,29 @@ static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
     return ret;
 }
 
+static int blockdev_amend_pre_run(BlockdevAmendJob *s, Error **errp)
+{
+    if (s->bs->drv->bdrv_amend_pre_run) {
+        return s->bs->drv->bdrv_amend_pre_run(s->bs, errp);
+    }
+
+    return 0;
+}
+
+static void blockdev_amend_clean(Job *job)
+{
+    BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
+
+    if (s->bs->drv->bdrv_amend_clean) {
+        s->bs->drv->bdrv_amend_clean(s->bs);
+    }
+}
+
 static const JobDriver blockdev_amend_job_driver = {
     .instance_size = sizeof(BlockdevAmendJob),
     .job_type      = JOB_TYPE_AMEND,
     .run           = blockdev_amend_run,
+    .clean         = blockdev_amend_clean,
 };
 
 void qmp_x_blockdev_amend(const char *job_id,
@@ -113,5 +132,11 @@ void qmp_x_blockdev_amend(const char *job_id,
     s->bs = bs,
     s->opts = QAPI_CLONE(BlockdevAmendOptions, options),
     s->force = has_force ? force : false;
+
+    if (blockdev_amend_pre_run(s, errp)) {
+        job_early_fail(&s->common);
+        return;
+    }
+
     job_start(&s->common);
 }
diff --git a/block/crypto.c b/block/crypto.c
index c8ba4681e2..70b2f07351 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -777,6 +777,37 @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
     return spec_info;
 }
 
+static int
+block_crypto_amend_prepare(BlockDriverState *bs, Error **errp)
+{
+    BlockCrypto *crypto = bs->opaque;
+    int ret;
+
+    /* apply for exclusive read/write permissions to the underlying file */
+    crypto->updating_keys = true;
+    ret = bdrv_child_refresh_perms(bs, bs->file, errp);
+    if (ret < 0) {
+        /* Well, in this case we will not be updating any keys */
+        crypto->updating_keys = false;
+    }
+    return ret;
+}
+
+static void
+block_crypto_amend_cleanup(BlockDriverState *bs)
+{
+    BlockCrypto *crypto = bs->opaque;
+    Error *errp = NULL;
+
+    /* release exclusive read/write permissions to the underlying file */
+    crypto->updating_keys = false;
+    bdrv_child_refresh_perms(bs, bs->file, &errp);
+
+    if (errp) {
+        error_report_err(errp);
+    }
+}
+
 static int
 block_crypto_amend_options_generic_luks(BlockDriverState *bs,
                                         QCryptoBlockAmendOptions *amend_options,
@@ -931,6 +962,8 @@ static BlockDriver bdrv_crypto_luks = {
     .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
     .bdrv_amend_options = block_crypto_amend_options_luks,
     .bdrv_co_amend      = block_crypto_co_amend_luks,
+    .bdrv_amend_pre_run = block_crypto_amend_prepare,
+    .bdrv_amend_clean   = block_crypto_amend_cleanup,
 
     .is_format          = true,
 
diff --git a/tests/qemu-iotests/296 b/tests/qemu-iotests/296
index 099a3eeaa5..f80ef3434a 100755
--- a/tests/qemu-iotests/296
+++ b/tests/qemu-iotests/296
@@ -174,8 +174,12 @@ class EncryptionSetupTestCase(iotests.QMPTestCase):
         }
 
         result = vm.qmp('x-blockdev-amend', **args)
-        assert result['return'] == {}
-        vm.run_job('job0')
+        iotests.log(result)
+        # Run the job only if it was created
+        event = ('JOB_STATUS_CHANGE',
+                 {'data': {'id': 'job0', 'status': 'created'}})
+        if vm.events_wait([event], timeout=0.0) is not None:
+            vm.run_job('job0')
 
     # test that when the image opened by two qemu processes,
     # neither of them can update the encryption keys
diff --git a/tests/qemu-iotests/296.out b/tests/qemu-iotests/296.out
index 42205cc981..609826eaa0 100644
--- a/tests/qemu-iotests/296.out
+++ b/tests/qemu-iotests/296.out
@@ -1,11 +1,9 @@
 
-{"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
-Job failed: Failed to get shared "consistent read" lock
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
-Job failed: Failed to get shared "consistent read" lock
-{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"error": {"class": "GenericError", "desc": "Failed to get shared \"consistent read\" lock"}}
+{"error": {"class": "GenericError", "desc": "Failed to get shared \"consistent read\" lock"}}
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
@@ -13,14 +11,9 @@ qemu-img: Failed to get shared "consistent read" lock
 Is another process using the image [TEST_DIR/test.img]?
 
 .
-Job failed: Block node is read-only
-{"execute": "job-dismiss", "arguments": {"id": "job0"}}
-{"return": {}}
-Job failed: Failed to get shared "consistent read" lock
-{"execute": "job-dismiss", "arguments": {"id": "job0"}}
-{"return": {}}
-Job failed: Failed to get shared "consistent read" lock
-{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"error": {"class": "GenericError", "desc": "Block node is read-only"}}
+{"error": {"class": "GenericError", "desc": "Failed to get shared \"consistent read\" lock"}}
+{"error": {"class": "GenericError", "desc": "Failed to get shared \"consistent read\" lock"}}
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
-- 
2.35.1



  reply	other threads:[~2022-03-04 16:49 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-04 16:46 [PULL 00/50] Block layer patches Kevin Wolf
2022-03-04 16:46 ` Kevin Wolf [this message]
2022-03-04 16:46 ` [PULL 02/50] crypto: distinguish between main loop and I/O in block_crypto_amend_options_generic_luks Kevin Wolf
2022-03-04 16:46 ` [PULL 03/50] block: introduce bdrv_activate Kevin Wolf
2022-03-04 16:46 ` [PULL 04/50] block: rename bdrv_invalidate_cache_all, blk_invalidate_cache and test_sync_op_invalidate_cache Kevin Wolf
2022-03-04 16:46 ` [PULL 05/50] block: move BQL logic of bdrv_co_invalidate_cache in bdrv_activate Kevin Wolf
2022-03-04 16:46 ` [PULL 06/50] tls: add macros for coroutine-safe TLS variables Kevin Wolf
2022-03-04 16:46 ` [PULL 07/50] util/async: replace __thread with QEMU TLS macros Kevin Wolf
2022-03-04 16:46 ` [PULL 08/50] rcu: use coroutine " Kevin Wolf
2022-03-04 16:46 ` [PULL 09/50] cpus: use coroutine TLS macros for iothread_locked Kevin Wolf
2022-03-04 16:46 ` [PULL 10/50] os-posix: Add os_set_daemonize() Kevin Wolf
2022-03-04 16:46 ` [PULL 11/50] qsd: Add pre-init argument parsing pass Kevin Wolf
2022-03-04 16:46 ` [PULL 12/50] qsd: Add --daemonize Kevin Wolf
2022-03-04 16:46 ` [PULL 13/50] iotests/185: Add post-READY quit tests Kevin Wolf
2022-03-04 16:46 ` [PULL 14/50] main-loop.h: introduce qemu_in_main_thread() Kevin Wolf
2022-03-04 16:46 ` [PULL 15/50] main loop: macros to mark GS and I/O functions Kevin Wolf
2022-03-04 16:46 ` [PULL 16/50] include/block/block: split header into I/O and global state API Kevin Wolf
2022-03-04 16:46 ` [PULL 17/50] assertions for block " Kevin Wolf
2022-03-04 16:46 ` [PULL 18/50] IO_CODE and IO_OR_GS_CODE for block I/O API Kevin Wolf
2022-03-04 16:46 ` [PULL 19/50] block/export/fuse.c: allow writable exports to take RESIZE permission Kevin Wolf
2022-03-04 16:46 ` [PULL 20/50] include/sysemu/block-backend: split header into I/O and global state (GS) API Kevin Wolf
2022-03-04 16:46 ` [PULL 21/50] block/block-backend.c: assertions for block-backend Kevin Wolf
2022-03-16 12:44   ` Philippe Mathieu-Daudé
2022-03-16 12:53     ` Philippe Mathieu-Daudé
2022-03-16 14:46       ` Emanuele Giuseppe Esposito
2022-03-16 15:25         ` Philippe Mathieu-Daudé
2022-03-16 16:02           ` Kevin Wolf
2022-03-16 12:54     ` Emanuele Giuseppe Esposito
2022-03-04 16:46 ` [PULL 22/50] IO_CODE and IO_OR_GS_CODE for block-backend I/O API Kevin Wolf
2022-03-04 16:46 ` [PULL 23/50] block.c: assertions to the block layer permissions API Kevin Wolf
2022-03-04 16:46 ` [PULL 24/50] include/block/block_int: split header into I/O and global state API Kevin Wolf
2022-03-04 16:46 ` [PULL 25/50] assertions for block_int " Kevin Wolf
2022-03-04 16:46 ` [PULL 26/50] IO_CODE and IO_OR_GS_CODE for block_int I/O API Kevin Wolf
2022-03-04 16:46 ` [PULL 27/50] block: introduce assert_bdrv_graph_writable Kevin Wolf
2022-03-04 16:46 ` [PULL 28/50] include/block/blockjob_int.h: split header into I/O and GS API Kevin Wolf
2022-03-04 16:46 ` [PULL 29/50] GS and IO CODE macros for blockjob_int.h Kevin Wolf
2022-03-04 16:46 ` [PULL 30/50] block.c: add assertions to static functions Kevin Wolf
2022-03-04 16:46 ` [PULL 31/50] include/block/blockjob.h: global state API Kevin Wolf
2022-03-04 16:46 ` [PULL 32/50] assertions for blockjob.h " Kevin Wolf
2022-03-04 16:46 ` [PULL 33/50] include/sysemu/blockdev.h: " Kevin Wolf
2022-03-04 16:46 ` [PULL 34/50] assertions for blockdev.h " Kevin Wolf
2022-03-04 16:46 ` [PULL 35/50] include/block/snapshot: global state API + assertions Kevin Wolf
2022-03-04 16:46 ` [PULL 36/50] block/copy-before-write.h: " Kevin Wolf
2022-03-04 16:46 ` [PULL 37/50] block/coroutines: I/O and "I/O or GS" API Kevin Wolf
2022-03-04 16:46 ` [PULL 38/50] block_int-common.h: split function pointers in BlockDriver Kevin Wolf
2022-03-04 16:47 ` [PULL 39/50] block_int-common.h: assertions in the callers of BlockDriver function pointers Kevin Wolf
2022-03-04 16:47 ` [PULL 40/50] block_int-common.h: split function pointers in BdrvChildClass Kevin Wolf
2022-03-04 16:47 ` [PULL 41/50] block_int-common.h: assertions in the callers of BdrvChildClass function pointers Kevin Wolf
2022-03-04 16:47 ` [PULL 42/50] block-backend-common.h: split function pointers in BlockDevOps Kevin Wolf
2022-03-04 16:47 ` [PULL 43/50] job.h: split function pointers in JobDriver Kevin Wolf
2022-03-04 16:47 ` [PULL 44/50] job.h: assertions in the callers of JobDriver function pointers Kevin Wolf
2022-03-04 16:47 ` [PULL 45/50] block: Make bdrv_refresh_limits() non-recursive Kevin Wolf
2022-03-04 16:47 ` [PULL 46/50] iotests: Allow using QMP with the QSD Kevin Wolf
2022-03-04 16:47 ` [PULL 47/50] iotests/graph-changes-while-io: New test Kevin Wolf
2022-03-04 16:47 ` [PULL 48/50] tests/qemu-iotests: Rework the checks and spots using GNU sed Kevin Wolf
2022-03-04 16:47 ` [PULL 49/50] block/amend: Always call .bdrv_amend_clean() Kevin Wolf
2022-03-04 16:47 ` [PULL 50/50] block/amend: Keep strong reference to BDS Kevin Wolf
2022-03-05 14:43 ` [PULL 00/50] Block layer patches Peter Maydell

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=20220304164711.474713-2-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=peter.maydell@linaro.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).