[PATCH 1/2] nvmet: take subsys->lock when forcing reconnects for tbkas
From: shao.mingyin
Date: Tue Nov 03 2026 - 14:53:54 EST
nvmet_subsys_attr_tbkas_store() walks subsys->ctrls to force a reconnect
while holding only nvmet_config_sem. The list is protected by
subsys->lock: nvmet_alloc_ctrl() adds entries and nvmet_ctrl_free()
removes them under that lock, and the controller free path does not take
nvmet_config_sem. Writing attr_tbkas concurrently with a controller
going away, for example on a keep-alive timeout or a fatal error, can
therefore dereference a controller that has already been removed and
freed.
Take subsys->lock around the list walk, as
nvmet_subsys_attr_qid_max_store() already does for the same loop.
delete_ctrl() only schedules the asynchronous teardown, so it does not
recurse into subsys->lock.
Fixes: e98e45e9465b ("nvmet: Add traffic based keep alive support to configfs")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
Tested on 7.3.0-next-20261030 (QEMU/TCG guest, KASAN) with the loop
transport.
One process hammers the attr_tbkas store while another connects and
deletes loop controllers, so the walk over subsys->ctrls races with
nvmet_ctrl_free():
unpatched patched
general protection fault, no report in 60 s,
KASAN wild-memory-access 0xdead... 39591 iterations
in nvmet_subsys_attr_tbkas_store
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index b3a5242d06f9..c17f2c8ab2df 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1466,8 +1466,10 @@ static ssize_t nvmet_subsys_attr_tbkas_store(struct config_item *item,
subsys->tbkas = tbkas;
/* Force reconnect */
+ mutex_lock(&subsys->lock);
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
ctrl->ops->delete_ctrl(ctrl);
+ mutex_unlock(&subsys->lock);
up_write(&nvmet_config_sem);
return count;