[PATCH] nvmet: do not copy beyond sybsysnqn string length
Shin'ichiro Kawasaki
shinichiro.kawasaki at wdc.com
Sat Dec 20 23:37:14 PST 2025
Commit edd17206e363 ("nvmet: remove redundant subsysnqn field from
ctrl") replaced ctrl->subsysnqn with ctrl->subsys->subsysnqn. This
change works as expected because both point to strings with the same
data. However, their memory allocation lengths differ. ctrl->subsysnqn
has the fixed size defined as NVMF_NQN_FILED_LEN, while
ctrl->subsys->subsysnqn has variable length determined by kstrndup().
Due to this difference, KASAN slab-out-of-bounds occurs at memcpy() in
nvmet_passthru_override_id_ctrl() after the commit. The failure can be
recreated by running the blktests test case nvme/033. To prevent such
failures, replace memcpy() with strscpy(), which copies only the string
length and avoids overruns.
Fixes: edd17206e363 ("nvmet: remove redundant subsysnqn field from ctrl")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
---
FYI, here I share the WARN which caused the blktestes nvme/033 failure.
[ 32.011546] [ T994] run blktests nvme/033 at 2025-12-20 20:49:57
[ 32.176786] [ T81] nvmet: Created nvm controller 1 for subsystem blktests-subsystem-1 for NQN nqn.2014-08.org.nvmexpress:uuid:0f01fb42-9f7f-4856-b0b3-51e60b8de349.
[ 32.181701] [ T81] ==================================================================
[ 32.182619] [ T81] BUG: KASAN: slab-out-of-bounds in nvmet_passthru_execute_cmd_work+0xe0a/0x1750 [nvmet]
[ 32.183718] [ T81] Read of size 256 at addr ffff888146030fc0 by task kworker/u16:4/81
p
[ 32.184899] [ T81] CPU: 1 UID: 0 PID: 81 Comm: kworker/u16:4 Not tainted 6.19.0-rc1+ #69 PREEMPT(voluntary)
[ 32.184903] [ T81] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-8.fc42 06/10/2025
[ 32.184905] [ T81] Workqueue: nvmet-wq nvmet_passthru_execute_cmd_work [nvmet]
[ 32.184919] [ T81] Call Trace:
[ 32.184921] [ T81] <TASK>
[ 32.184923] [ T81] dump_stack_lvl+0x6a/0x90
[ 32.184939] [ T81] ? nvmet_passthru_execute_cmd_work+0xe0a/0x1750 [nvmet]
[ 32.184950] [ T81] print_report+0x170/0x4f3
[ 32.184954] [ T81] ? __virt_addr_valid+0x22e/0x500
[ 32.184958] [ T81] ? nvmet_passthru_execute_cmd_work+0xe0a/0x1750 [nvmet]
[ 32.184969] [ T81] kasan_report+0xad/0x150
[ 32.184974] [ T81] ? nvmet_passthru_execute_cmd_work+0xe0a/0x1750 [nvmet]
[ 32.184986] [ T81] kasan_check_range+0x115/0x1f0
[ 32.184989] [ T81] __asan_memcpy+0x1f/0x60
[ 32.184991] [ T81] nvmet_passthru_execute_cmd_work+0xe0a/0x1750 [nvmet]
[ 32.185003] [ T81] ? lock_acquire+0x16a/0x2f0
[ 32.185008] [ T81] ? __pfx_nvmet_passthru_execute_cmd_work+0x10/0x10 [nvmet]
[ 32.185019] [ T81] ? lock_acquire+0x17a/0x2f0
[ 32.185021] [ T81] ? process_one_work+0x722/0x1490
[ 32.185024] [ T81] ? lock_release+0x1ab/0x2f0
[ 32.185027] [ T81] process_one_work+0x868/0x1490
[ 32.185031] [ T81] ? __pfx_process_one_work+0x10/0x10
[ 32.185033] [ T81] ? lock_acquire+0x16a/0x2f0
[ 32.185037] [ T81] ? assign_work+0x156/0x390
[ 32.185040] [ T81] worker_thread+0x5ee/0xfd0
[ 32.185044] [ T81] ? __pfx_worker_thread+0x10/0x10
[ 32.185046] [ T81] kthread+0x3af/0x770
[ 32.185049] [ T81] ? lock_acquire+0x17a/0x2f0
[ 32.185051] [ T81] ? __pfx_kthread+0x10/0x10
[ 32.185053] [ T81] ? __pfx_kthread+0x10/0x10
[ 32.185055] [ T81] ? ret_from_fork+0x6e/0x810
[ 32.185058] [ T81] ? lock_release+0x1ab/0x2f0
[ 32.185060] [ T81] ? rcu_is_watching+0x11/0xb0
[ 32.185062] [ T81] ? __pfx_kthread+0x10/0x10
[ 32.185064] [ T81] ret_from_fork+0x55c/0x810
[ 32.185066] [ T81] ? __pfx_ret_from_fork+0x10/0x10
[ 32.185068] [ T81] ? __switch_to+0x10a/0xda0
[ 32.185072] [ T81] ? __switch_to_asm+0x33/0x70
[ 32.185074] [ T81] ? __pfx_kthread+0x10/0x10
[ 32.185077] [ T81] ret_from_fork_asm+0x1a/0x30
[ 32.185081] [ T81] </TASK>
[ 32.211854] [ T81] Allocated by task 1052:
[ 32.212651] [ T81] kasan_save_stack+0x2c/0x50
[ 32.213499] [ T81] kasan_save_track+0x10/0x30
[ 32.214313] [ T81] __kasan_kmalloc+0x96/0xb0
[ 32.215104] [ T81] __kmalloc_node_track_caller_noprof+0x2e7/0x8d0
[ 32.216072] [ T81] kstrndup+0x53/0xe0
[ 32.216784] [ T81] nvmet_subsys_alloc+0x243/0x680 [nvmet]
[ 32.217710] [ T81] nvmet_subsys_make+0x95/0x480 [nvmet]
[ 32.218585] [ T81] configfs_mkdir+0x457/0xb30
[ 32.219365] [ T81] vfs_mkdir+0x615/0x970
[ 32.220093] [ T81] do_mkdirat+0x3a1/0x500
[ 32.220813] [ T81] __x64_sys_mkdir+0xd3/0x160
[ 32.221583] [ T81] do_syscall_64+0x95/0x540
[ 32.222333] [ T81] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 32.223734] [ T81] The buggy address belongs to the object at ffff888146030fc0
which belongs to the cache kmalloc-32 of size 32
[ 32.225728] [ T81] The buggy address is located 0 bytes inside of
allocated 21-byte region [ffff888146030fc0, ffff888146030fd5)
[ 32.228244] [ T81] The buggy address belongs to the physical page:
[ 32.229238] [ T81] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x146030
[ 32.230466] [ T81] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
[ 32.231539] [ T81] page_type: f5(slab)
[ 32.232239] [ T81] raw: 0017ffffc0000000 ffff888100042780 dead000000000122 0000000000000000
[ 32.233443] [ T81] raw: 0000000000000000 0000000000400040 00000000f5000000 0000000000000000
[ 32.234692] [ T81] page dumped because: kasan: bad access detected
[ 32.236259] [ T81] Memory state around the buggy address:
[ 32.237135] [ T81] ffff888146030e80: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
[ 32.238303] [ T81] ffff888146030f00: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
[ 32.239531] [ T81] >ffff888146030f80: fa fb fb fb fc fc fc fc 00 00 05 fc fc fc fc fc
[ 32.240676] [ T81] ^
[ 32.241679] [ T81] ffff888146031000: fa fb fb fb fb fb fb fb fc fc fc fc fa fb fb fb
[ 32.242843] [ T81] ffff888146031080: fb fb fb fb fc fc fc fc fa fb fb fb fb fb fb fb
[ 32.244019] [ T81] ==================================================================
[ 32.245229] [ T81] Disabling lock debugging due to kernel taint
[ 32.247366] [ T1063] nvme nvme5: creating 4 I/O queues.
[ 32.249203] [ T1063] nvme nvme5: new ctrl: "blktests-subsystem-1"
[ 32.251921] [ T86] nvme nvme5: Duplicate unshared namespace 1
[ 37.389407] [ T86] nvme nvme5: Removing ctrl: NQN "nqn.2019-08.org.qemu:deadbeef"
[ 38.286242] [ T1179] SoftiWARP attached
[ 38.349942] [ T994] run blktests nvme/033 at 2025-12-20 20:50:03
drivers/nvme/target/passthru.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 96648ec2fadb..67c423a8b052 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -150,7 +150,7 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
* code path with duplicate ctrl subsysnqn. In order to prevent that we
* mask the passthru-ctrl subsysnqn with the target ctrl subsysnqn.
*/
- memcpy(id->subnqn, ctrl->subsys->subsysnqn, sizeof(id->subnqn));
+ strscpy(id->subnqn, ctrl->subsys->subsysnqn, sizeof(id->subnqn));
/* use fabric id-ctrl values */
id->ioccsz = cpu_to_le32((sizeof(struct nvme_command) +
--
2.52.0
More information about the Linux-nvme
mailing list