[PATCH] scsi: target: use kref_get_unless_zero() in core_get_se_deve_from_rtpi()
From: Yifei Gao
Date: Tue Aug 04 2026 - 17:40:55 EST
core_get_se_deve_from_rtpi() iterates nacl->lun_entry_hlist under
rcu_read_lock() and takes a plain kref_get() on deve->pr_kref for the
matching entry. The disable path, core_disable_device_list_for_node(),
unhashes the entry, drops the final reference, waits for pr_comp and
frees it via call_rcu() while holding lun_entry_mutex, which the reader
does not hold. A reader racing that path can revive the kref after it has
reached zero, defeating the pr_comp completion barrier and leading to a
use-after-free.
Use kref_get_unless_zero() and skip entries whose refcount has already
dropped to zero.
Fixes: 29a05deebf6c ("target: Convert se_node_acl->device_list[] to RCU hlist")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Yifei Gao <gyf161023@xxxxxxxxx>
---
drivers/target/target_core_device.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 9db2201aa553..bff97c6efffb 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -220,7 +220,8 @@ struct se_dev_entry *core_get_se_deve_from_rtpi(
if (lun->lun_tpg->tpg_rtpi != rtpi)
continue;
- kref_get(&deve->pr_kref);
+ if (!kref_get_unless_zero(&deve->pr_kref))
+ continue;
rcu_read_unlock();
return deve;
--
2.43.0