summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaokun Li <libaokun@linux.alibaba.com>2026-10-23 16:19:08 +0800
committerJens Axboe <axboe@kernel.dk>2026-10-29 11:10:05 -0600
commitc8c53d669d4e45b3a804013251a34387d7e11bfb (patch)
treef80fb1015e7e5e6e68c3d17d0112862dd99037c5
parent0c10f8a1a7ae1502ea4ea7e13f222df89c28adf4 (diff)
downloadlinux-c8c53d669d4e45b3a804013251a34387d7e11bfb.tar.gz
linux-c8c53d669d4e45b3a804013251a34387d7e11bfb.zip
blk-crypto: fix NULL deref and UAF in __blk_crypto_evict_key()
Sashiko reported a possible NULL pointer dereference, triggered by the following flow: dm-inlinecrypt ctor # first use of the fallback ├─ blk_crypto_init_key() # succeeds, ctx->key.size != 0 ├─ blk_crypto_start_using_key() │ ├─ hw-wrapped key: -EOPNOTSUPP │ │ # profile never allocated (NULL) │ └─ raw key: fallback_start_using_mode() │ └─ blk_crypto_fallback_init() fails │ └─ kfree(profile) # not NULLed ├─ goto bad └─ inlinecrypt_dtr() # evicts whenever key.size is set └─ blk_crypto_evict_key() └─ blk_crypto_config_supported_natively() = false └─ blk_crypto_fallback_evict_key() └─ __blk_crypto_evict_key(blk_crypto_fallback_profile) └─ profile->num_slots # BOOM!!! This issue can be reproduced using the following commands: dd if=/dev/zero of=/tmp/backing bs=1M count=64 LOOP=$(losetup -f --show /tmp/backing) SZ=$(blockdev --getsz $LOOP) KEY=$(head -c 64 /dev/urandom | od -An -tx1 | tr -d ' \n') dmsetup create ic --table "0 $SZ inlinecrypt aes-xts-plain64 \ $KEY 0 $LOOP 0 1 keytype:hw-wrapped" And the following oops is triggered: ================================================================== blk-crypto: loop0: no support for wrapped keys Oops: general protection fault, probably for non-canonical address 0xdffffc000000000b: 0000 [#1] SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000058-0x000000000000005f] CPU: 5 UID: 0 PID: 901 Comm: dmsetup 7.3.0-rc3 #1 PREEMPT(lazy) RIP: 0010:__blk_crypto_evict_key+0x2e/0x3b0 Call Trace: blk_crypto_evict_key+0x24c/0x320 inlinecrypt_dtr+0xf6/0x160 inlinecrypt_ctr+0x2d3/0xbd0 dm_table_add_target+0x661/0xf40 table_load+0x1c4/0x490 ctl_ioctl+0x32f/0x5f0 dm_ctl_ioctl+0xe/0x20 ================================================================== dm-inlinecrypt is the only caller that can evict a key that was never started, as fscrypt frees such a key without evicting it. Fix this by returning early from blk_crypto_fallback_evict_key() when tfms_inited[] is not set for the key's mode. tfms_inited[] is only set after blk_crypto_fallback_init() has successfully initialized the profile, so the crash above is no longer reachable. The bug has been latent since commit c984ff1423ae ("blk-crypto: dynamically allocate fallback profile") was merged in v6.5, and only became actually triggerable when commit e7f57d2c47e2 ("dm-inlinecrypt: add target for inline block device encryption") was merged in v7.2. Fixes: c984ff1423ae ("blk-crypto: dynamically allocate fallback profile") Cc: stable@vger.kernel.org Reported-by: Sashiko <sashiko-bot@kernel.org> Closes: https://patch.msgid.link/sashiko-outbox-167341@kernel.org Suggested-by: Eric Biggers <ebiggers@kernel.org> Link: https://patch.msgid.link/20261014155131.GB322435@quark Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Reviewed-by: Eric Biggers <ebiggers@kernel.org> Link: https://patch.msgid.link/20261023081908.3505413-1-libaokun@linux.alibaba.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/blk-crypto-fallback.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 2a8f40a65158..12e0b487e23a 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -524,6 +524,12 @@ bool blk_crypto_fallback_bio_prep(struct bio *bio)
int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key)
{
+ /*
+ * Pairs with smp_store_release() in
+ * blk_crypto_fallback_start_using_mode()
+ */
+ if (!smp_load_acquire(&tfms_inited[key->crypto_cfg.crypto_mode]))
+ return 0;
return __blk_crypto_evict_key(blk_crypto_fallback_profile, key);
}