From d326f904525adbaafe72ec4f06589f7db14855a0 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Wed, 16 Oct 2024 09:32:53 -0700 Subject: [PATCH] ANDROID: dm-default-key: Prevent kernel crash on invalid table When trying to create a device with an invalid table configuration, kernel would panic: For instance, table (note the number of argument 2, should be 1): "0 default-key aes-xts-plain64 0 0 2 allow_discards" Instead of an expected error message in kmsg: device-mapper: table: 254:24: default-key: Invalid number of feature args (-EINVAL) the kernel crashes: [ 48.701559] BUG: kernel NULL pointer dereference, address: 0000000000000040 ... [ 48.701702] ? exc_page_fault+0x4f/0xa0 [ 48.701709] ? asm_exc_page_fault+0x22/0x30 [ 48.701717] ? __blk_crypto_evict_key+0x18/0x190 [ 48.701722] blk_crypto_evict_key+0x41/0x90 [ 48.701731] default_key_ctr+0x22a/0x670 [dm_default_key 3355aa60cc2e380cc7745b7937dd463f0a9bc032] [ 48.701745] dm_table_add_target+0x1de/0x380 [ 48.701754] table_load+0x13b/0x3e0 [ 48.701763] ? __pfx_table_load+0x10/0x10 [ 48.701769] ctl_ioctl+0x180/0x240 [ 48.701777] dm_ctl_ioctl+0xe/0x20 The problem is the key is not initialized yet when the optional arguments are parsed. __blk_crypto_cfg_supported() expects the blk_crypto_config to be valid, but since it is not, return true and __blk_crypto_evict_key() gets called with a NULL profile argument. Prevent calling blk_crypto_evict_key() when the key size is not yet set. Bug: 160885805 Change-Id: Ife6f42bb0e32dff5173e77fadda1ed23bac7c8a9 Signed-off-by: Gwendal Grignou --- drivers/md/dm-default-key.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-default-key.c b/drivers/md/dm-default-key.c index c113279bf8d1..15c963ab907e 100644 --- a/drivers/md/dm-default-key.c +++ b/drivers/md/dm-default-key.c @@ -65,9 +65,11 @@ lookup_cipher(const char *cipher_string) static void default_key_dtr(struct dm_target *ti) { struct default_key_c *dkc = ti->private; + struct blk_crypto_key *blk_key = &dkc->key; if (dkc->dev) { - blk_crypto_evict_key(dkc->dev->bdev, &dkc->key); + if (blk_key->size > 0) + blk_crypto_evict_key(dkc->dev->bdev, blk_key); dm_put_device(ti, dkc->dev); } kfree_sensitive(dkc->cipher_string);