From patchwork Wed Mar 15 18:39:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 13176545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2ECEEC76196 for ; Wed, 15 Mar 2023 18:42:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231721AbjCOSmc (ORCPT ); Wed, 15 Mar 2023 14:42:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231743AbjCOSmb (ORCPT ); Wed, 15 Mar 2023 14:42:31 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D4D51E293; Wed, 15 Mar 2023 11:42:00 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id DECC761E20; Wed, 15 Mar 2023 18:40:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 20570C433D2; Wed, 15 Mar 2023 18:40:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678905632; bh=yBgzSkaPH6InVgy9hkj3HoXP1UJVqeWDnOyZNcN2omI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S9EFdT/MvdZGu0zdvxwoudHG4lnwPy7gYvYx04rcKzmL2pCQ5zAjAn6x0VQRXP9Ps O7J06/jbs7aGhGFVHHhSCtbrowGBF5nEhX0cT6MfOZGvpA66AQnTSonB5Q6n5qFiBj UYfOkW8SBNnvr0Dj0MGXSPzX1va8my7LmFuWrhMBZJdejkDAdljkiHyjG7gQ3ZPU/8 vL9HPclHo8UOvM/zQtpSNf5e/8iDFIHL1TpsnwF5Ecak4nHoGS11Xsafbzqs+eNgcV hOzAHzwXUdg8crcV76UyUb4rNxgObHE4J8kYNHudstDid00WA+0m4By40rXJN+R2rM 1Bx40Bm0ZTBLA== From: Eric Biggers To: linux-block@vger.kernel.org, Jens Axboe Cc: linux-fscrypt@vger.kernel.org, Nathan Huckleberry , stable@vger.kernel.org, Christoph Hellwig Subject: [PATCH v3 1/6] blk-mq: release crypto keyslot before reporting I/O complete Date: Wed, 15 Mar 2023 11:39:02 -0700 Message-Id: <20230315183907.53675-2-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230315183907.53675-1-ebiggers@kernel.org> References: <20230315183907.53675-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org From: Eric Biggers Once all I/O using a blk_crypto_key has completed, filesystems can call blk_crypto_evict_key(). However, the block layer currently doesn't call blk_crypto_put_keyslot() until the request is being freed, which happens after upper layers have been told (via bio_endio()) the I/O has completed. This causes a race condition where blk_crypto_evict_key() can see 'slot_refs != 0' without there being an actual bug. This makes __blk_crypto_evict_key() hit the 'WARN_ON_ONCE(atomic_read(&slot->slot_refs) != 0)' and return without doing anything, eventually causing a use-after-free in blk_crypto_reprogram_all_keys(). (This is a very rare bug and has only been seen when per-file keys are being used with fscrypt.) There are two options to fix this: either release the keyslot before bio_endio() is called on the request's last bio, or make __blk_crypto_evict_key() ignore slot_refs. Let's go with the first solution, since it preserves the ability to report bugs (via WARN_ON_ONCE) where a key is evicted while still in-use. Fixes: a892c8d52c02 ("block: Inline encryption support for blk-mq") Cc: stable@vger.kernel.org Reviewed-by: Nathan Huckleberry Reviewed-by: Christoph Hellwig Signed-off-by: Eric Biggers --- block/blk-crypto-internal.h | 25 +++++++++++++++++++++---- block/blk-crypto.c | 24 ++++++++++++------------ block/blk-merge.c | 2 ++ block/blk-mq.c | 15 ++++++++++++++- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h index a8cdaf26851e1..4f1de2495f0c3 100644 --- a/block/blk-crypto-internal.h +++ b/block/blk-crypto-internal.h @@ -65,6 +65,11 @@ static inline bool blk_crypto_rq_is_encrypted(struct request *rq) return rq->crypt_ctx; } +static inline bool blk_crypto_rq_has_keyslot(struct request *rq) +{ + return rq->crypt_keyslot; +} + blk_status_t blk_crypto_get_keyslot(struct blk_crypto_profile *profile, const struct blk_crypto_key *key, struct blk_crypto_keyslot **slot_ptr); @@ -119,6 +124,11 @@ static inline bool blk_crypto_rq_is_encrypted(struct request *rq) return false; } +static inline bool blk_crypto_rq_has_keyslot(struct request *rq) +{ + return false; +} + #endif /* CONFIG_BLK_INLINE_ENCRYPTION */ void __bio_crypt_advance(struct bio *bio, unsigned int bytes); @@ -153,14 +163,21 @@ static inline bool blk_crypto_bio_prep(struct bio **bio_ptr) return true; } -blk_status_t __blk_crypto_init_request(struct request *rq); -static inline blk_status_t blk_crypto_init_request(struct request *rq) +blk_status_t __blk_crypto_rq_get_keyslot(struct request *rq); +static inline blk_status_t blk_crypto_rq_get_keyslot(struct request *rq) { if (blk_crypto_rq_is_encrypted(rq)) - return __blk_crypto_init_request(rq); + return __blk_crypto_rq_get_keyslot(rq); return BLK_STS_OK; } +void __blk_crypto_rq_put_keyslot(struct request *rq); +static inline void blk_crypto_rq_put_keyslot(struct request *rq) +{ + if (blk_crypto_rq_has_keyslot(rq)) + __blk_crypto_rq_put_keyslot(rq); +} + void __blk_crypto_free_request(struct request *rq); static inline void blk_crypto_free_request(struct request *rq) { @@ -199,7 +216,7 @@ static inline blk_status_t blk_crypto_insert_cloned_request(struct request *rq) { if (blk_crypto_rq_is_encrypted(rq)) - return blk_crypto_init_request(rq); + return blk_crypto_rq_get_keyslot(rq); return BLK_STS_OK; } diff --git a/block/blk-crypto.c b/block/blk-crypto.c index 45378586151f7..d0c7feb447e96 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -224,27 +224,27 @@ static bool bio_crypt_check_alignment(struct bio *bio) return true; } -blk_status_t __blk_crypto_init_request(struct request *rq) +blk_status_t __blk_crypto_rq_get_keyslot(struct request *rq) { return blk_crypto_get_keyslot(rq->q->crypto_profile, rq->crypt_ctx->bc_key, &rq->crypt_keyslot); } -/** - * __blk_crypto_free_request - Uninitialize the crypto fields of a request. - * - * @rq: The request whose crypto fields to uninitialize. - * - * Completely uninitializes the crypto fields of a request. If a keyslot has - * been programmed into some inline encryption hardware, that keyslot is - * released. The rq->crypt_ctx is also freed. - */ -void __blk_crypto_free_request(struct request *rq) +void __blk_crypto_rq_put_keyslot(struct request *rq) { blk_crypto_put_keyslot(rq->crypt_keyslot); + rq->crypt_keyslot = NULL; +} + +void __blk_crypto_free_request(struct request *rq) +{ + /* The keyslot, if one was needed, should have been released earlier. */ + if (WARN_ON_ONCE(rq->crypt_keyslot)) + __blk_crypto_rq_put_keyslot(rq); + mempool_free(rq->crypt_ctx, bio_crypt_ctx_pool); - blk_crypto_rq_set_defaults(rq); + rq->crypt_ctx = NULL; } /** diff --git a/block/blk-merge.c b/block/blk-merge.c index 6460abdb24267..65e75efa9bd36 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -867,6 +867,8 @@ static struct request *attempt_merge(struct request_queue *q, if (!blk_discard_mergable(req)) elv_merge_requests(q, req, next); + blk_crypto_rq_put_keyslot(next); + /* * 'next' is going away, so update stats accordingly */ diff --git a/block/blk-mq.c b/block/blk-mq.c index d0cb2ef18fe21..49825538d932d 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -840,6 +840,12 @@ static void blk_complete_request(struct request *req) req->q->integrity.profile->complete_fn(req, total_bytes); #endif + /* + * Upper layers may call blk_crypto_evict_key() anytime after the last + * bio_endio(). Therefore, the keyslot must be released before that. + */ + blk_crypto_rq_put_keyslot(req); + blk_account_io_completion(req, total_bytes); do { @@ -905,6 +911,13 @@ bool blk_update_request(struct request *req, blk_status_t error, req->q->integrity.profile->complete_fn(req, nr_bytes); #endif + /* + * Upper layers may call blk_crypto_evict_key() anytime after the last + * bio_endio(). Therefore, the keyslot must be released before that. + */ + if (blk_crypto_rq_has_keyslot(req) && nr_bytes >= blk_rq_bytes(req)) + __blk_crypto_rq_put_keyslot(req); + if (unlikely(error && !blk_rq_is_passthrough(req) && !(req->rq_flags & RQF_QUIET)) && !test_bit(GD_DEAD, &req->q->disk->state)) { @@ -2967,7 +2980,7 @@ void blk_mq_submit_bio(struct bio *bio) blk_mq_bio_to_request(rq, bio, nr_segs); - ret = blk_crypto_init_request(rq); + ret = blk_crypto_rq_get_keyslot(rq); if (ret != BLK_STS_OK) { bio->bi_status = ret; bio_endio(bio); From patchwork Wed Mar 15 18:39:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 13176565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA338C7618D for ; Wed, 15 Mar 2023 18:46:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232237AbjCOSqS (ORCPT ); Wed, 15 Mar 2023 14:46:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44186 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230176AbjCOSqL (ORCPT ); Wed, 15 Mar 2023 14:46:11 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3CB1B18143; Wed, 15 Mar 2023 11:45:43 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id D0B25B81F0D; Wed, 15 Mar 2023 18:40:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 742DAC4339B; Wed, 15 Mar 2023 18:40:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678905632; bh=odC1xQHL7ynUb87om8IH745XnPEFBc3hWniPvn6Q4SU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JH6Fi9nbWsu4CkNpo3goCQSk1bUZToc/3murEXAd3cQQl/IPnIgsHzT6DGHyUkvsp 0FBySOVaEWlriYXRXuO6jEKL5U/yccz6R2IC7X8HAJbUvxDB5GehhI0FJlMWntCe+n qtoHrXRwWqwBgFArz3Sn0o8haxz+o+rIewjQHBE2lFkyZjNV68ZPTlBi2jReTC6Vl9 dZNjGA33gU9pIvzFrvqyMeVgkME3FiD87buqlfRpgs/JzOfAXf6AqRzdCRH0BPC6Jw ie90JCCsDuCv46BHpbMxC2TXL6XAYn//KhMULc6XgeXihEVhDWOUPkolkyOlvZ6b10 KebNaz/JcMDiQ== From: Eric Biggers To: linux-block@vger.kernel.org, Jens Axboe Cc: linux-fscrypt@vger.kernel.org, Nathan Huckleberry , stable@vger.kernel.org Subject: [PATCH v3 2/6] blk-crypto: make blk_crypto_evict_key() return void Date: Wed, 15 Mar 2023 11:39:03 -0700 Message-Id: <20230315183907.53675-3-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230315183907.53675-1-ebiggers@kernel.org> References: <20230315183907.53675-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org From: Eric Biggers blk_crypto_evict_key() is only called in contexts such as inode eviction where failure is not an option. So there is nothing the caller can do with errors except log them. (dm-table.c does "use" the error code, but only to pass on to upper layers, so it doesn't really count.) Just make blk_crypto_evict_key() return void and log errors itself. Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- block/blk-crypto.c | 20 +++++++++----------- drivers/md/dm-table.c | 19 +++++-------------- include/linux/blk-crypto.h | 4 ++-- 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/block/blk-crypto.c b/block/blk-crypto.c index d0c7feb447e96..e800f305e9eda 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "blk-crypto-internal.h" @@ -408,21 +409,18 @@ int blk_crypto_start_using_key(struct block_device *bdev, * Upper layers (filesystems) must call this function to ensure that a key is * evicted from any hardware that it might have been programmed into. The key * must not be in use by any in-flight IO when this function is called. - * - * Return: 0 on success or if the key wasn't in any keyslot; -errno on error. */ -int blk_crypto_evict_key(struct block_device *bdev, - const struct blk_crypto_key *key) +void blk_crypto_evict_key(struct block_device *bdev, + const struct blk_crypto_key *key) { struct request_queue *q = bdev_get_queue(bdev); + int err; if (blk_crypto_config_supported_natively(bdev, &key->crypto_cfg)) - return __blk_crypto_evict_key(q->crypto_profile, key); - - /* - * If the block_device didn't support the key, then blk-crypto-fallback - * may have been used, so try to evict the key from blk-crypto-fallback. - */ - return blk_crypto_fallback_evict_key(key); + err = __blk_crypto_evict_key(q->crypto_profile, key); + else + err = blk_crypto_fallback_evict_key(key); + if (err) + pr_warn_ratelimited("%pg: error %d evicting key\n", bdev, err); } EXPORT_SYMBOL_GPL(blk_crypto_evict_key); diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2055a758541de..7899f5fb4c133 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1202,21 +1202,12 @@ struct dm_crypto_profile { struct mapped_device *md; }; -struct dm_keyslot_evict_args { - const struct blk_crypto_key *key; - int err; -}; - static int dm_keyslot_evict_callback(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { - struct dm_keyslot_evict_args *args = data; - int err; + const struct blk_crypto_key *key = data; - err = blk_crypto_evict_key(dev->bdev, args->key); - if (!args->err) - args->err = err; - /* Always try to evict the key from all devices. */ + blk_crypto_evict_key(dev->bdev, key); return 0; } @@ -1229,7 +1220,6 @@ static int dm_keyslot_evict(struct blk_crypto_profile *profile, { struct mapped_device *md = container_of(profile, struct dm_crypto_profile, profile)->md; - struct dm_keyslot_evict_args args = { key }; struct dm_table *t; int srcu_idx; @@ -1242,11 +1232,12 @@ static int dm_keyslot_evict(struct blk_crypto_profile *profile, if (!ti->type->iterate_devices) continue; - ti->type->iterate_devices(ti, dm_keyslot_evict_callback, &args); + ti->type->iterate_devices(ti, dm_keyslot_evict_callback, + (void *)key); } dm_put_live_table(md, srcu_idx); - return args.err; + return 0; } static int diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h index 1e3e5d0adf120..5e5822c18ee41 100644 --- a/include/linux/blk-crypto.h +++ b/include/linux/blk-crypto.h @@ -95,8 +95,8 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, int blk_crypto_start_using_key(struct block_device *bdev, const struct blk_crypto_key *key); -int blk_crypto_evict_key(struct block_device *bdev, - const struct blk_crypto_key *key); +void blk_crypto_evict_key(struct block_device *bdev, + const struct blk_crypto_key *key); bool blk_crypto_config_supported_natively(struct block_device *bdev, const struct blk_crypto_config *cfg); From patchwork Wed Mar 15 18:39:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 13176543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80466C7618D for ; Wed, 15 Mar 2023 18:42:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231942AbjCOSm3 (ORCPT ); Wed, 15 Mar 2023 14:42:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35776 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231452AbjCOSm2 (ORCPT ); Wed, 15 Mar 2023 14:42:28 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3E1481E2AB; Wed, 15 Mar 2023 11:41:52 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 3CCBAB81F10; Wed, 15 Mar 2023 18:40:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF979C4339E; Wed, 15 Mar 2023 18:40:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678905632; bh=xqR7r+TSfrM+1ggDX5VsWh7dG6I0faiObGb5WTWlPls=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hs2ReypwUOQ+yPSoxnkjgv0+w8IYrrypnVrZ9R3ua/EqCvfqsfk0tnyTgN2Q4Yux4 JSJPaGrXYIm9Ie0leV9RJju2nBh5TGLSdTakwRIuFiiDU/RyaKbKcf7uWTw/YlslOB 1w/Cl24OoFfBfF7/M3bZwI5Bv1u/1afFgGV+XOTU1KtLDzIoYlslvObRGF76Wh0HeD zqZNVaPdF/7ZdUjcCh7qXh7G5pa6I8JvXzHzmyt01lGxi3zIDTTWOVAoTlhpIFgnbR jr503VLvXXLXrHkzvuQUDL0MVLswT2OW/KvvVJekbJ2dDGdlRmm3mbx8L3ZN2HShno nq2LrMqww2ZAw== From: Eric Biggers To: linux-block@vger.kernel.org, Jens Axboe Cc: linux-fscrypt@vger.kernel.org, Nathan Huckleberry , stable@vger.kernel.org Subject: [PATCH v3 3/6] blk-crypto: make blk_crypto_evict_key() more robust Date: Wed, 15 Mar 2023 11:39:04 -0700 Message-Id: <20230315183907.53675-4-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230315183907.53675-1-ebiggers@kernel.org> References: <20230315183907.53675-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org From: Eric Biggers If blk_crypto_evict_key() sees that the key is still in-use (due to a bug) or that ->keyslot_evict failed, it currently just returns while leaving the key linked into the keyslot management structures. However, blk_crypto_evict_key() is only called in contexts such as inode eviction where failure is not an option. So actually the caller proceeds with freeing the blk_crypto_key regardless of the return value of blk_crypto_evict_key(). These two assumptions don't match, and the result is that there can be a use-after-free in blk_crypto_reprogram_all_keys() after one of these errors occurs. (Note, these errors *shouldn't* happen; we're just talking about what happens if they do anyway.) Fix this by making blk_crypto_evict_key() unlink the key from the keyslot management structures even on failure. Also improve some comments. Fixes: 1b2628397058 ("block: Keyslot Manager for Inline Encryption") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- block/blk-crypto-profile.c | 46 +++++++++++++++++--------------------- block/blk-crypto.c | 28 ++++++++++++++++------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c index 0307fb0d95d34..3290c03c9918d 100644 --- a/block/blk-crypto-profile.c +++ b/block/blk-crypto-profile.c @@ -354,28 +354,16 @@ bool __blk_crypto_cfg_supported(struct blk_crypto_profile *profile, return true; } -/** - * __blk_crypto_evict_key() - Evict a key from a device. - * @profile: the crypto profile of the device - * @key: the key to evict. It must not still be used in any I/O. - * - * If the device has keyslots, this finds the keyslot (if any) that contains the - * specified key and calls the driver's keyslot_evict function to evict it. - * - * Otherwise, this just calls the driver's keyslot_evict function if it is - * implemented, passing just the key (without any particular keyslot). This - * allows layered devices to evict the key from their underlying devices. - * - * Context: Process context. Takes and releases profile->lock. - * Return: 0 on success or if there's no keyslot with the specified key, -EBUSY - * if the keyslot is still in use, or another -errno value on other - * error. +/* + * This is an internal function that evicts a key from an inline encryption + * device that can be either a real device or the blk-crypto-fallback "device". + * It is used only by blk_crypto_evict_key(); see that function for details. */ int __blk_crypto_evict_key(struct blk_crypto_profile *profile, const struct blk_crypto_key *key) { struct blk_crypto_keyslot *slot; - int err = 0; + int err; if (profile->num_slots == 0) { if (profile->ll_ops.keyslot_evict) { @@ -389,22 +377,30 @@ int __blk_crypto_evict_key(struct blk_crypto_profile *profile, blk_crypto_hw_enter(profile); slot = blk_crypto_find_keyslot(profile, key); - if (!slot) - goto out_unlock; + if (!slot) { + /* + * Not an error, since a key not in use by I/O is not guaranteed + * to be in a keyslot. There can be more keys than keyslots. + */ + err = 0; + goto out; + } if (WARN_ON_ONCE(atomic_read(&slot->slot_refs) != 0)) { + /* BUG: key is still in use by I/O */ err = -EBUSY; - goto out_unlock; + goto out_remove; } err = profile->ll_ops.keyslot_evict(profile, key, blk_crypto_keyslot_index(slot)); - if (err) - goto out_unlock; - +out_remove: + /* + * Callers free the key even on error, so unlink the key from the hash + * table and clear slot->key even on error. + */ hlist_del(&slot->hash_node); slot->key = NULL; - err = 0; -out_unlock: +out: blk_crypto_hw_exit(profile); return err; } diff --git a/block/blk-crypto.c b/block/blk-crypto.c index e800f305e9eda..4d760b092deb9 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -400,15 +400,19 @@ int blk_crypto_start_using_key(struct block_device *bdev, } /** - * blk_crypto_evict_key() - Evict a key from any inline encryption hardware - * it may have been programmed into - * @bdev: The block_device who's associated inline encryption hardware this key - * might have been programmed into - * @key: The key to evict + * blk_crypto_evict_key() - Evict a blk_crypto_key from a block_device + * @bdev: a block_device on which I/O using the key may have been done + * @key: the key to evict * - * Upper layers (filesystems) must call this function to ensure that a key is - * evicted from any hardware that it might have been programmed into. The key - * must not be in use by any in-flight IO when this function is called. + * For a given block_device, this function removes the given blk_crypto_key from + * the keyslot management structures and evicts it from any underlying hardware + * keyslot(s) or blk-crypto-fallback keyslot it may have been programmed into. + * + * Upper layers must call this before freeing the blk_crypto_key. It must be + * called for every block_device the key may have been used on. The key must no + * longer be in use by any I/O when this function is called. + * + * Context: May sleep. */ void blk_crypto_evict_key(struct block_device *bdev, const struct blk_crypto_key *key) @@ -420,6 +424,14 @@ void blk_crypto_evict_key(struct block_device *bdev, err = __blk_crypto_evict_key(q->crypto_profile, key); else err = blk_crypto_fallback_evict_key(key); + /* + * An error can only occur here if the key failed to be evicted from a + * keyslot (due to a hardware or driver issue) or is allegedly still in + * use by I/O (due to a kernel bug). Even in these cases, the key is + * still unlinked from the keyslot management structures, and the caller + * is allowed and expected to free it right away. There's nothing + * callers can do to handle errors, so just log them and return void. + */ if (err) pr_warn_ratelimited("%pg: error %d evicting key\n", bdev, err); } From patchwork Wed Mar 15 18:39:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 13176544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59683C761A6 for ; Wed, 15 Mar 2023 18:42:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231743AbjCOSmd (ORCPT ); Wed, 15 Mar 2023 14:42:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35776 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231290AbjCOSmb (ORCPT ); Wed, 15 Mar 2023 14:42:31 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F04613D5D; Wed, 15 Mar 2023 11:42:01 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 8CD0EB81F11; Wed, 15 Mar 2023 18:40:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16590C4339C; Wed, 15 Mar 2023 18:40:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678905633; bh=2JTrHPUW27A/tQAHzBOXIsvbeN7mv3S3zqMhXaryO1Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SfpCBNs31LkF0oivffKi3HSh8d5xwBD1KUQ5RmVmVm7w6agOXdAxlH74MXCoBxxNh L5N0hqZcwple5b/SKjbSVE3A/oN4yfzvwJi7UEqgVL5fWedGWXUPbP7BIy8EeijqZv BSw5JMtGXzDy6FwAb6cOPdMDOkZHeLWTfC8C4LqDrbrZPjNHfNGHHL+9hXO+y/+8q5 cpg3TO56W/3WLMRGVWwruYcG9UDkMUJeh2yS7J6oiiT+FGoSGbMUUSQ50skB2Jqb5H R4HQjQVEPtot9cmfJx6e2Ca8FME7FSnZ61XFFScyI3X9vF4CyKzyQmffbtyLBS6//i C262KpEKE7T/A== From: Eric Biggers To: linux-block@vger.kernel.org, Jens Axboe Cc: linux-fscrypt@vger.kernel.org, Nathan Huckleberry Subject: [PATCH v3 4/6] blk-crypto: remove blk_crypto_insert_cloned_request() Date: Wed, 15 Mar 2023 11:39:05 -0700 Message-Id: <20230315183907.53675-5-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230315183907.53675-1-ebiggers@kernel.org> References: <20230315183907.53675-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org From: Eric Biggers blk_crypto_insert_cloned_request() is the same as blk_crypto_rq_get_keyslot(), so just use that directly. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- Documentation/block/inline-encryption.rst | 3 +-- block/blk-crypto-internal.h | 15 --------------- block/blk-mq.c | 2 +- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/Documentation/block/inline-encryption.rst b/Documentation/block/inline-encryption.rst index f9bf18ea65093..90b733422ed46 100644 --- a/Documentation/block/inline-encryption.rst +++ b/Documentation/block/inline-encryption.rst @@ -270,8 +270,7 @@ Request queue based layered devices like dm-rq that wish to support inline encryption need to create their own blk_crypto_profile for their request_queue, and expose whatever functionality they choose. When a layered device wants to pass a clone of that request to another request_queue, blk-crypto will -initialize and prepare the clone as necessary; see -``blk_crypto_insert_cloned_request()``. +initialize and prepare the clone as necessary. Interaction between inline encryption and blk integrity ======================================================= diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h index 4f1de2495f0c3..93a141979694b 100644 --- a/block/blk-crypto-internal.h +++ b/block/blk-crypto-internal.h @@ -205,21 +205,6 @@ static inline int blk_crypto_rq_bio_prep(struct request *rq, struct bio *bio, return 0; } -/** - * blk_crypto_insert_cloned_request - Prepare a cloned request to be inserted - * into a request queue. - * @rq: the request being queued - * - * Return: BLK_STS_OK on success, nonzero on error. - */ -static inline blk_status_t blk_crypto_insert_cloned_request(struct request *rq) -{ - - if (blk_crypto_rq_is_encrypted(rq)) - return blk_crypto_rq_get_keyslot(rq); - return BLK_STS_OK; -} - #ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num); diff --git a/block/blk-mq.c b/block/blk-mq.c index 49825538d932d..5e819de2f5e70 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3049,7 +3049,7 @@ blk_status_t blk_insert_cloned_request(struct request *rq) if (q->disk && should_fail_request(q->disk->part0, blk_rq_bytes(rq))) return BLK_STS_IOERR; - if (blk_crypto_insert_cloned_request(rq)) + if (blk_crypto_rq_get_keyslot(rq)) return BLK_STS_IOERR; blk_account_io_start(rq); From patchwork Wed Mar 15 18:39:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 13176542 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5E27DC61DA4 for ; Wed, 15 Mar 2023 18:42:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230106AbjCOSmQ (ORCPT ); Wed, 15 Mar 2023 14:42:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231290AbjCOSmP (ORCPT ); Wed, 15 Mar 2023 14:42:15 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5F1F313DDA; Wed, 15 Mar 2023 11:41:47 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 1A02861E50; Wed, 15 Mar 2023 18:40:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5BFCAC433D2; Wed, 15 Mar 2023 18:40:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678905633; bh=JxQjRBgYS6KrYKBuMUapr6XvhJ+sb1I8bM5e+bk8euE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ppeym9PMY1rGkTvyOtpcNq7n09HVCZWOSk/S1LQuOY9TSPs3KU5TJXxoiPGsDhdYx gB+llmbKXowE09KA+dfykisJMMLxeTuDiZuxdB76QKzIuNw1zN1uB0XEM2wyxuDrKw gYcyM1Gj1QdnkOS+4+j9Wm7zrsQe5DHBrm0gej1NUL3jSB/hfGpjuuBk4oXMIFCiyX +2EScC8Cu3EvHZ4L6MeRY9JpoRBRz7YeR/BnKzqJ/VFaZEg7U0VGLbpDVsQ1j91AbJ Wbk/Y27x/DpeZDsFI8ToBT8F7g9fznwTNfkxfdKZnVKgbWjZtxxwzceANXG7KJAq7I u8Eo4z0sf5zjQ== From: Eric Biggers To: linux-block@vger.kernel.org, Jens Axboe Cc: linux-fscrypt@vger.kernel.org, Nathan Huckleberry Subject: [PATCH v3 5/6] blk-mq: return actual keyslot error in blk_insert_cloned_request() Date: Wed, 15 Mar 2023 11:39:06 -0700 Message-Id: <20230315183907.53675-6-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230315183907.53675-1-ebiggers@kernel.org> References: <20230315183907.53675-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org From: Eric Biggers To avoid hiding information, pass on the error code from blk_crypto_rq_get_keyslot() instead of always using BLK_STS_IOERR. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- block/blk-mq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 5e819de2f5e70..a875b1cdff9b5 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3049,8 +3049,9 @@ blk_status_t blk_insert_cloned_request(struct request *rq) if (q->disk && should_fail_request(q->disk->part0, blk_rq_bytes(rq))) return BLK_STS_IOERR; - if (blk_crypto_rq_get_keyslot(rq)) - return BLK_STS_IOERR; + ret = blk_crypto_rq_get_keyslot(rq); + if (ret != BLK_STS_OK) + return ret; blk_account_io_start(rq); From patchwork Wed Mar 15 18:39:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 13176569 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8DBAC6FD1D for ; Wed, 15 Mar 2023 18:49:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231536AbjCOSt3 (ORCPT ); Wed, 15 Mar 2023 14:49:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232190AbjCOSt2 (ORCPT ); Wed, 15 Mar 2023 14:49:28 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A02A911E96; Wed, 15 Mar 2023 11:49:00 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 21B10B81F0F; Wed, 15 Mar 2023 18:40:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A1D0FC433A0; Wed, 15 Mar 2023 18:40:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678905633; bh=nxXzrV07OaXxqVH25OB7zwsJ+hxE6DhfHAt+jgSYsdQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vp8062PukWtWA7LIfozadkUw6LhUAjVFW0Vy1SoX+FDhz652uRPmd3kpiPeG/w1mQ fSx03d5Q65gxi/4brtX9CFJNMvH8Q4N0Fp7hgj+Qvy0b+F8IJkrNRx2TN5ZDZx3Y0y PCun7TYVL7SE+pmkNUcPobnnX5ntqyFD5CBYa64tTaUKTCFEs74QSf3iUzXF0dtdLv ciiaOsYRCxCZZNH59hZrO7vidRgA/wyH8lVO5S+KJXC6YlAPppYk0AW1sWRUMqHeDm zZ+rJASuw0QAuppSmPwuqAmvzR05AynwHkVBN+tCdu1KSi+KPdjeBmYmc7tN23vFGO HjzmMfWPbR83w== From: Eric Biggers To: linux-block@vger.kernel.org, Jens Axboe Cc: linux-fscrypt@vger.kernel.org, Nathan Huckleberry , Christoph Hellwig Subject: [PATCH v3 6/6] blk-crypto: drop the NULL check from blk_crypto_put_keyslot() Date: Wed, 15 Mar 2023 11:39:07 -0700 Message-Id: <20230315183907.53675-7-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230315183907.53675-1-ebiggers@kernel.org> References: <20230315183907.53675-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org From: Eric Biggers Now that all callers of blk_crypto_put_keyslot() check for NULL before calling it, there is no need for blk_crypto_put_keyslot() to do the NULL check itself. Reviewed-by: Christoph Hellwig Signed-off-by: Eric Biggers --- block/blk-crypto-profile.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c index 3290c03c9918d..2a67d3fb63e5c 100644 --- a/block/blk-crypto-profile.c +++ b/block/blk-crypto-profile.c @@ -227,14 +227,13 @@ EXPORT_SYMBOL_GPL(blk_crypto_keyslot_index); * @profile: the crypto profile of the device the key will be used on * @key: the key that will be used * @slot_ptr: If a keyslot is allocated, an opaque pointer to the keyslot struct - * will be stored here; otherwise NULL will be stored here. + * will be stored here. blk_crypto_put_keyslot() must be called + * later to release it. Otherwise, NULL will be stored here. * * If the device has keyslots, this gets a keyslot that's been programmed with * the specified key. If the key is already in a slot, this reuses it; * otherwise this waits for a slot to become idle and programs the key into it. * - * This must be paired with a call to blk_crypto_put_keyslot(). - * * Context: Process context. Takes and releases profile->lock. * Return: BLK_STS_OK on success, meaning that either a keyslot was allocated or * one wasn't needed; or a blk_status_t error on failure. @@ -312,20 +311,15 @@ blk_status_t blk_crypto_get_keyslot(struct blk_crypto_profile *profile, /** * blk_crypto_put_keyslot() - Release a reference to a keyslot - * @slot: The keyslot to release the reference of (may be NULL). + * @slot: The keyslot to release the reference of * * Context: Any context. */ void blk_crypto_put_keyslot(struct blk_crypto_keyslot *slot) { - struct blk_crypto_profile *profile; + struct blk_crypto_profile *profile = slot->profile; unsigned long flags; - if (!slot) - return; - - profile = slot->profile; - if (atomic_dec_and_lock_irqsave(&slot->slot_refs, &profile->idle_slots_lock, flags)) { list_add_tail(&slot->idle_slot_node, &profile->idle_slots);