[PATCH AUTOSEL 6.17-5.10] nvme-fc: use lock accessing port_state and rport state

Sasha Levin sashal at kernel.org
Thu Oct 9 08:56:07 PDT 2025


From: Daniel Wagner <wagi at kernel.org>

[ Upstream commit 891cdbb162ccdb079cd5228ae43bdeebce8597ad ]

nvme_fc_unregister_remote removes the remote port on a lport object at
any point in time when there is no active association. This races with
with the reconnect logic, because nvme_fc_create_association is not
taking a lock to check the port_state and atomically increase the
active count on the rport.

Reported-by: Shinichiro Kawasaki <shinichiro.kawasaki at wdc.com>
Closes: https://lore.kernel.org/all/u4ttvhnn7lark5w3sgrbuy2rxupcvosp4qmvj46nwzgeo5ausc@uyrkdls2muwx
Signed-off-by: Daniel Wagner <wagi at kernel.org>
Reviewed-by: Hannes Reinecke <hare at suse.de>
Signed-off-by: Keith Busch <kbusch at kernel.org>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---

LLM Generated explanations, may be completely bogus:

YES
- Adds the missing synchronization in `nvme_fc_create_association()` so
  we hold `rport->lock` while checking `remoteport.port_state` and
  bumping `act_ctrl_cnt` via `nvme_fc_ctlr_active_on_rport()`
  (`drivers/nvme/host/fc.c:3034-3044`). That makes the state check and
  reference grab atomic with respect to other rport users.
- Without this lock, `nvme_fc_unregister_remoteport()` can flip the same
  `remoteport.port_state` and tear down the rport under lock
  (`drivers/nvme/host/fc.c:813-839`) while a reconnect path is still
  between the state check and the `act_ctrl_cnt` increment
  (`drivers/nvme/host/fc.c:2987-2999`). This window lets the reconnect
  code touch freed memory or miss the counter bump, causing crashes or
  failed reconnections—the bug reported on the mailing list.
- The fix is tightly scoped to this race, no API or behavioral changes
  elsewhere, and it follows existing locking rules for the rport. The
  affected logic is unchanged across supported stable branches, so the
  patch applies cleanly and removes a long-standing use-after-free
  hazard.

 drivers/nvme/host/fc.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 3e12d4683ac72..03987f497a5b5 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -3032,11 +3032,17 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
 
 	++ctrl->ctrl.nr_reconnects;
 
-	if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
+	spin_lock_irqsave(&ctrl->rport->lock, flags);
+	if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE) {
+		spin_unlock_irqrestore(&ctrl->rport->lock, flags);
 		return -ENODEV;
+	}
 
-	if (nvme_fc_ctlr_active_on_rport(ctrl))
+	if (nvme_fc_ctlr_active_on_rport(ctrl)) {
+		spin_unlock_irqrestore(&ctrl->rport->lock, flags);
 		return -ENOTUNIQ;
+	}
+	spin_unlock_irqrestore(&ctrl->rport->lock, flags);
 
 	dev_info(ctrl->ctrl.device,
 		"NVME-FC{%d}: create association : host wwpn 0x%016llx "
-- 
2.51.0




More information about the Linux-nvme mailing list