Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH] IB/isert: reject login PDUs shorter than ISER_HEADERS_LEN
@ 2026-06-02 19:46 Michael Bommarito
  2026-06-05 16:18 ` Jason Gunthorpe
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Bommarito @ 2026-06-02 19:46 UTC (permalink / raw)
  To: Sagi Grimberg, Jason Gunthorpe, Leon Romanovsky
  Cc: linux-rdma, target-devel, linux-kernel

In drivers/infiniband/ulp/isert/ib_isert.c, isert_login_recv_done()
computes the login request payload length as wc->byte_len minus
ISER_HEADERS_LEN with no lower bound, and login_req_len is a signed int.
A remote iSER initiator can post a login Send work request carrying
fewer than ISER_HEADERS_LEN (76) bytes, so the subtraction underflows
and login_req_len becomes negative.

isert_rx_login_req() then reads that negative length back into a signed
int, takes size = min(rx_buflen, MAX_KEY_VALUE_PAIRS), and because the
min() is signed it keeps the negative value; the value is then passed as
the memcpy() length and sign-extended to a multi-gigabyte size_t. The
copy into the 8192-byte login->req_buf runs far out of bounds and
faults, crashing the target node. The login phase precedes iSCSI
authentication, so no credentials are required to reach this path.

Reject any login PDU shorter than ISER_HEADERS_LEN before the
subtraction, mirroring the existing early return on a failed work
completion, so login_req_len can never go negative. The upper bound was
already safe: a posted login buffer cannot deliver more than
ISER_RX_PAYLOAD_SIZE, so the difference stays at or below
MAX_KEY_VALUE_PAIRS and the existing min() clamps it; only the missing
lower bound needs to be added.

Fixes: b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---

Impact: a remote, pre-auth iSER initiator can crash an iSER-enabled LIO
target by sending a single login PDU shorter than ISER_HEADERS_LEN,
underflowing login_req_len to a negative value that drives an
out-of-bounds memcpy.

Analysis
========

Tree: mainline a1f173eb51db (7.1-rc4 line), x86_64.

ISER_HEADERS_LEN is sizeof(struct iser_ctrl) (28, __packed) plus
sizeof(struct iscsi_hdr) (48) = 76. login_req_len is a signed int
(ib_isert.h). For a received login Send with wc->byte_len in 1..75,
isert_login_recv_done() stores wc->byte_len - ISER_HEADERS_LEN, which
underflows to a negative int. isert_rx_login_req() reads it back as
int rx_buflen, computes size = min(rx_buflen, MAX_KEY_VALUE_PAIRS)
(MAX_KEY_VALUE_PAIRS is 8192; the min is signed so size stays
negative), and calls memcpy(login->req_buf, isert_get_data(rx_desc),
size). login->req_buf is an 8192-byte kzalloc in the iSCSI target login
path. The negative size sign-extends to a multi-gigabyte size_t at
memcpy(), so the copy runs out of bounds of req_buf and faults.

Conditions: an RDMA transport plus an iSER-enabled LIO target. iSER is
enabled per portal (targetcli enable_iser); a plain iSCSI-over-TCP
target does not load this path. RoCEv2 and iWARP transports are
routable, so the initiator need not share the target's L2 segment;
RoCEv1 and native InfiniBand require an adjacent initiator. The
malformed login Send is accepted during the login phase, before iSCSI
authentication, so no credentials are required.

The upper bound is already safe: a posted login receive buffer cannot
deliver more than ISER_RX_PAYLOAD_SIZE, so wc->byte_len - 76 stays at
or below MAX_KEY_VALUE_PAIRS and the existing min() clamps it. Only the
missing lower bound is added here. The initiator-side iSER receive path
rejects short receives; the target login path had no equivalent floor.

With the patch, a login Send shorter than ISER_HEADERS_LEN is dropped
in isert_login_recv_done() (the new early return logs "login request
length N is too short") and login_req_len is left untouched, so the
downstream min()/memcpy() length stays within the 8192-byte buffer; a
well-formed login (wc->byte_len >= 76) is unaffected. The defect is
identified by static analysis of the cited code paths; the path can be
exercised by driving a short login Send at an rxe-backed iSER LIO
target under KASAN.

 drivers/infiniband/ulp/isert/ib_isert.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 348005e71891c..a849a420be421 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1383,6 +1383,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 	ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr,
 			ISER_RX_SIZE, DMA_FROM_DEVICE);
 
+	if (unlikely(wc->byte_len < ISER_HEADERS_LEN)) {
+		isert_err("login request length %u is too short\n",
+			  wc->byte_len);
+		return;
+	}
+
 	isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN;
 
 	if (isert_conn->conn) {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-06-05 16:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-02 19:46 [PATCH] IB/isert: reject login PDUs shorter than ISER_HEADERS_LEN Michael Bommarito
2026-06-05 16:18 ` Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox