[PATCH v2 2/2] IB/isert: reject full-feature PDUs that arrive before registration
From: Yehyeong Lee
Date: Thu Jul 30 2026 - 02:43:44 EST
The full-feature receive buffers are posted from isert_put_login_tx(),
which runs before __transport_register_session(). An initiator that does
not wait for the final Login Response can therefore still have a SCSI
command executed against an se_session whose se_tpg is NULL, with the same
oops as the previous patch.
Move the ISER_CONN_FULL_FEATURE transition into isert_get_rx_pdu(), where
it happens after the session has been registered, and reinstate the
connection on any PDU that arrives before it, the same call this function
already makes when a work completion fails. A full-feature PDU before the
login has completed is a protocol violation. The state is read without
isert_conn->mutex because isert_recv_done() runs on ib-comp-wq.
Measured over rxe with an initiator that fires SCSI commands into that
window without waiting for the Login Response, 400 login cycles per run:
the oops appeared in 6 of 10 runs with only the previous patch applied and
in 0 of 10 runs with this one on top. The check fired 24 times across
those 10 runs, always in ISER_CONN_BOUND. Well-formed traffic is
unaffected: the regression set passes 10/10 and a 400-cycle churn passes
400/400 with the check never firing.
Fixes: b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
New in v2. Depends on 1/2 and must not be backported without it.
drivers/infiniband/ulp/isert/ib_isert.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 93f2fec942dd..2a322df5202c 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -952,11 +952,6 @@ isert_put_login_tx(struct iscsit_conn *conn, struct iscsi_login *login,
if (ret)
return ret;
- /* Now we are in FULL_FEATURE phase */
- mutex_lock(&isert_conn->mutex);
- isert_conn->state = ISER_CONN_FULL_FEATURE;
- mutex_unlock(&isert_conn->mutex);
-
/* Sent from isert_get_rx_pdu() after registration. */
isert_conn->login_rsp_pending = true;
return 0;
@@ -1331,6 +1326,14 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
return;
}
+ /* A full-feature PDU before registration is a protocol violation. */
+ if (unlikely(READ_ONCE(isert_conn->state) != ISER_CONN_FULL_FEATURE)) {
+ isert_err("PDU received in state %d, resetting connection\n",
+ isert_conn->state);
+ iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+ return;
+ }
+
rx_desc->in_use = true;
ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
@@ -2594,6 +2597,12 @@ static void isert_get_rx_pdu(struct iscsit_conn *conn)
/* The session is registered by now; see isert_put_login_tx(). */
if (isert_conn->login_rsp_pending) {
isert_conn->login_rsp_pending = false;
+
+ /* Now we are in FULL_FEATURE phase */
+ mutex_lock(&isert_conn->mutex);
+ isert_conn->state = ISER_CONN_FULL_FEATURE;
+ mutex_unlock(&isert_conn->mutex);
+
if (isert_login_post_send(isert_conn,
&isert_conn->login_tx_desc))
return;
--
2.43.0