[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