* [PATCH] blk-crypto: fix NULL deref and UAF in __blk_crypto_evict_key()
@ 2026-10-13 9:51 Baokun Li
2026-10-13 10:13 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Baokun Li @ 2026-10-13 9:51 UTC (permalink / raw)
To: axboe, linux-block
Cc: ebiggers, linux-fscrypt, hch, bvanassche, dm-devel, mpatocka,
linlin.zhang, libaokun, stable, Sashiko
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()
│ ├─ return -EOPNOTSUPP # uninit profile, will NULL deref
│ └─ blk_crypto_fallback_start_using_key()
│ └─ blk_crypto_fallback_init() fails
│ └─ kfree(profile) # not NULLed, will UAF
├─ 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
==================================================================
Fix this by checking the profile for NULL in __blk_crypto_evict_key()
to avoid the NULL pointer dereference, and by clearing the profile
pointer after it is freed to avoid the use-after-free.
Fixes: e7f57d2c47e2 ("dm-inlinecrypt: add target for inline block device encryption")
Cc: stable@vger.kernel.org # v7.2+
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://patch.msgid.link/sashiko-outbox-167341@kernel.org
Signed-off-by: Baokun Li <libaokun@linux.alibaba.com>
---
block/blk-crypto-fallback.c | 1 +
block/blk-crypto-profile.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 2a8f40a65158..b7890ee1951c 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -605,6 +605,7 @@ static int blk_crypto_fallback_init(void)
blk_crypto_profile_destroy(blk_crypto_fallback_profile);
fail_free_profile:
kfree(blk_crypto_fallback_profile);
+ blk_crypto_fallback_profile = NULL;
fail_free_bioset:
bioset_exit(&enc_bio_set);
out:
diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c
index 53126c091b0b..1c5feca3b856 100644
--- a/block/blk-crypto-profile.c
+++ b/block/blk-crypto-profile.c
@@ -346,6 +346,9 @@ int __blk_crypto_evict_key(struct blk_crypto_profile *profile,
struct blk_crypto_keyslot *slot;
int err;
+ if (!profile)
+ return 0;
+
if (profile->num_slots == 0) {
if (profile->ll_ops.keyslot_evict) {
blk_crypto_hw_enter(profile);
base-commit: fd73f4a6659897191fa0d40695fe370925dd3780
--
2.43.7
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] blk-crypto: fix NULL deref and UAF in __blk_crypto_evict_key()
2026-10-13 9:51 [PATCH] blk-crypto: fix NULL deref and UAF in __blk_crypto_evict_key() Baokun Li
@ 2026-10-13 10:13 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-13 10:13 UTC (permalink / raw)
To: Baokun Li, axboe
Cc: ebiggers, linux-fscrypt, hch, bvanassche, mpatocka, linlin.zhang
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] block: concurrent UAF in __blk_crypto_evict_key() via lockless global read
--
commit e07e1c7433e60b079101f4843a8706bcb93632f8
Author: Baokun Li <libaokun@linux.alibaba.com>
blk-crypto: fix NULL deref and UAF in __blk_crypto_evict_key()
This patch attempts to resolve a NULL pointer dereference and a
use-after-free by checking for a NULL profile in __blk_crypto_evict_key()
and clearing the fallback profile pointer after freeing it on the error
path.
Closes: https://patch.msgid.link/sashiko-outbox-167341@kernel.org
> diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
> index 2a8f40a65158b..b7890ee1951c7 100644
> --- a/block/blk-crypto-fallback.c
> +++ b/block/blk-crypto-fallback.c
[ ... ]
> @@ -605,6 +605,7 @@ static int blk_crypto_fallback_init(void)
> blk_crypto_profile_destroy(blk_crypto_fallback_profile);
> fail_free_profile:
> kfree(blk_crypto_fallback_profile);
> + blk_crypto_fallback_profile = NULL;
[Severity: High]
Does this change leave a concurrent use-after-free window open?
In blk_crypto_fallback_init(), the global pointer is published before
initialization is complete:
blk_crypto_fallback_profile = kzalloc_obj(*blk_crypto_fallback_profile);
If another thread concurrently executes blk_crypto_fallback_evict_key(),
it can locklessly read the global blk_crypto_fallback_profile. If the
initialization thread encounters an error and frees the profile:
kfree(blk_crypto_fallback_profile);
Could the evicting thread end up reading the pointer before the kfree()
occurs and subsequently dereferencing the freed memory? Setting the pointer
to NULL after it is freed might not prevent a data race if the pointer was
already copied by the evicting thread.
> fail_free_bioset:
> bioset_exit(&enc_bio_set);
> out:
> diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c
> index 53126c091b0be..1c5feca3b856a 100644
> --- a/block/blk-crypto-profile.c
> +++ b/block/blk-crypto-profile.c
> @@ -346,6 +346,9 @@ int __blk_crypto_evict_key(struct blk_crypto_profile *profile,
> struct blk_crypto_keyslot *slot;
> int err;
>
> + if (!profile)
> + return 0;
> +
> if (profile->num_slots == 0) {
[Severity: High]
Because the profile pointer is passed in after being read locklessly by the
caller, could this pointer still point to freed memory if the initialization
thread freed it concurrently?
If so, the new NULL check would be bypassed, and reading profile->num_slots
would trigger a use-after-free.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261013095106.881914-1-libaokun@linux.alibaba.com?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-13 10:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 9:51 [PATCH] blk-crypto: fix NULL deref and UAF in __blk_crypto_evict_key() Baokun Li
2026-10-13 10:13 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox