[PATCH] scsi: target: tcm_fc: use kref_get_unless_zero() in ft_sess_get()

Yifei Gao <[email protected]>
Newsgroups org.kernel.vger.target-devel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-scsi,org.kernel.vger.stable
Message-ID <[email protected]>
ft_sess_get() walks the RCU-protected session hash under rcu_read_lock()
and takes a plain kref_get() on a matching session. Session teardown does
hlist_del_rcu() and then drops ft_lport_lock before the final
ft_sess_put() -> kfree_rcu(). A reader that is preempted between the
port_id comparison and the kref_get() can therefore revive a session whose
refcount has already dropped to zero and is pending free, leading to a
use-after-free and a double target_remove_session().

Use kref_get_unless_zero() and treat a zero refcount as "not found",
matching the standard pattern for RCU lookups that race with kref-based
teardown.

Fixes: 3699d92a4d7b ("[SCSI] tcm_fc: Adding FC_FC4 provider (tcm_fc) for FCoE target (TCM - target core) support")
Cc: [email protected]
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Yifei Gao <[email protected]>
---
 drivers/target/tcm_fc/tfc_sess.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 797be06ab71b..1bc7d2dcbea3 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -172,7 +172,8 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
 	head = &tport->hash[ft_sess_hash(port_id)];
 	hlist_for_each_entry_rcu(sess, head, hash) {
 		if (sess->port_id == port_id) {
-			kref_get(&sess->kref);
+			if (!kref_get_unless_zero(&sess->kref))
+				break;
 			rcu_read_unlock();
 			TFC_SESS_DBG(lport, "port_id %x found %p\n",
 				     port_id, sess);
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.