All of lore.kernel.org
 help / color / mirror / Atom feed
From: Youngsung Ahn <ays511.kr@gmail.com>
To: Zhu Yanjun <yanjun.zhu@linux.dev>, Leon Romanovsky <leon@kernel.org>
Cc: linux-rdma@vger.kernel.org
Subject: [PATCH v3] RDMA/rxe: bound the WQE opcode before indexing rxe_wr_opcode_info[]
Date: Sat,  3 Oct 2026 01:45:52 +0900	[thread overview]
Message-ID: <20261002164552.294749-1-ays511.kr@gmail.com> (raw)

wr_opcode_mask() indexes the global rxe_wr_opcode_info[] array with
a caller-supplied opcode and no bounds check. For a user QP the WQE
comes from an mmap'd SQ ring, so wqe->wr.opcode is an
attacker-controlled __u32 read back by the requester
(req_next_wqe() -> rxe_requester()); rxe_post_send() takes the
qp->is_user branch and never runs validate_send_wr(), whose only
opcode check is itself !wr_opcode_mask() (it indexes before it
checks). rxe_wr_opcode_info[] has entries only up to IB_WR_REG_MR,
so an out-of-range opcode reads out of bounds and the result is used
as a mask and dereferenced; observed as a KASAN global-out-of-bounds
"Read of size 4" and a wild-pointer oops.

Return a zero mask for an out-of-range opcode, matching how
validate_send_wr() already treats a zero mask (an invalid WR), so no
path indexes the array out of bounds.

Fixes: 8700e3e7c485 ("Soft RoCE driver")
Signed-off-by: Youngsung Ahn <ays511.kr@gmail.com>
Assisted-by: LLM
---
Notes (not part of the commit):
v3: no code change. Sent as a standalone message rather than as a reply to
the v2 posting, and dropped the Cc: stable@vger.kernel.org trailer, both
as asked on-list.

On the question about req_retry(): req_retry() does not reject the WQE
itself, it only re-posts it. A zero mask makes every "mask & WR_*" test
there false, so an out-of-range opcode yields iova = 0, the dma cursor
reset, and neither retry_first_write_send() nor the read fix-up; the WQE
is left in wqe_state_posted. Once the requester dispatches it, wqe->mask
stays 0 so WR_LOCAL_OP_MASK is not taken, and next_opcode() matches no
case for an out-of-range wqe->wr.opcode and returns -EINVAL, so
rxe_requester() sets wqe->status = IB_WC_LOC_QP_OP_ERR and takes the err
path, which moves the QP to IB_QPS_ERR and lets the completer post the
completion.

wr_opcode_mask() is the single choke point all three callers
(validate_send_wr(), req_next_wqe(), req_retry()) funnel through, and only
validate_send_wr() rejects the WQE on a zero mask. In req_retry()
wr_opcode_mask() is called at the top of the loop body, before the
wqe_state_posted / wqe_state_done checks, so the out-of-bounds read
happens even for WQEs the loop then skips.

ARRAY_SIZE() is not usable here: rxe_opcode.h only declares "extern
struct rxe_wr_opcode_info rxe_wr_opcode_info[]". IB_WR_REG_MR (32) is the
highest index initialised in rxe_opcode.c, and on x86-64 the object is
1320 bytes with a 40-byte stride, i.e. 33 elements, so valid indices are
0..32.

The bug was reproduced on an unpatched KASAN x86-64 build of 7.3-rc4, with
the reproducer run as uid 1000 (the splat itself is attributed to the
rxe_wq kworker, since that is where the WQE is consumed): KASAN
global-out-of-bounds read of size 4 at rxe_wr_opcode_info, and an Oops or
GPF for larger opcodes. Present unchanged in mainline 551c722f4080
(2026-09-29). This patch itself is only compile-tested (KASAN +
CONFIG_RDMA_RXE). I am posting the reproducer on-list in reply to the v2
discussion of this patch.

 drivers/infiniband/sw/rxe/rxe_loc.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h
index 64d636bf80fd..dcc0788db90a 100644
--- a/drivers/infiniband/sw/rxe/rxe_loc.h
+++ b/drivers/infiniband/sw/rxe/rxe_loc.h
@@ -184,6 +184,9 @@ void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb);
 
 static inline unsigned int wr_opcode_mask(int opcode, struct rxe_qp *qp)
 {
+	if (unlikely(opcode < 0 || opcode > IB_WR_REG_MR))
+		return 0;
+
 	return rxe_wr_opcode_info[opcode].mask[qp->ibqp.qp_type];
 }
 
-- 
2.43.0


             reply	other threads:[~2026-10-02 16:46 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-02 16:45 Youngsung Ahn [this message]
2026-10-03  1:33 ` [PATCH v3] RDMA/rxe: bound the WQE opcode before indexing rxe_wr_opcode_info[] sashiko-bot
2026-10-04  3:40 ` Zhu Yanjun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261002164552.294749-1-ays511.kr@gmail.com \
    --to=ays511.kr@gmail.com \
    --cc=leon@kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=yanjun.zhu@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.