Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH v2] RDMA/rxe: bound the WQE opcode before indexing rxe_wr_opcode_info[]
       [not found] <20260930180221.2497908-1-ays511.kr@gmail.com>
@ 2026-10-01 15:24 ` Youngsung Ahn
  2026-10-01 17:50   ` Zhu Yanjun
  0 siblings, 1 reply; 2+ messages in thread
From: Youngsung Ahn @ 2026-10-01 15:24 UTC (permalink / raw)
  To: Zhu Yanjun; +Cc: linux-rdma, Youngsung Ahn, stable

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")
Cc: stable@vger.kernel.org
Signed-off-by: Youngsung Ahn <ays511.kr@gmail.com>
Assisted-by: LLM
---
Notes (not part of the commit):
Reproduced on a KASAN x86-64 build of 7.3-rc4 as uid 1000. Present unchanged
in mainline 551c722f4080 (2026-09-29) and rdma for-next. Compile-tested
(KASAN+RDMA_RXE), not runtime-tested. Per security-bugs.rst this is public and
a reproducer can be shared on request. IB_WR_REG_MR is the highest index the
array initializes; an ARRAY_SIZE(rxe_wr_opcode_info) bound would be equivalent
but the array is extern to this header.

v2: no code change. The irregular indentation in v1 was email mangling (HTML),
not a coding-style problem -- as Willy Tarreau noted on the ODP thread; resent
as plain text with tabs preserved via git send-email. Added Cc: stable, fixed
the author/Signed-off-by match, and added Assisted-by: LLM.

 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

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

* Re: [PATCH v2] RDMA/rxe: bound the WQE opcode before indexing rxe_wr_opcode_info[]
  2026-10-01 15:24 ` [PATCH v2] RDMA/rxe: bound the WQE opcode before indexing rxe_wr_opcode_info[] Youngsung Ahn
@ 2026-10-01 17:50   ` Zhu Yanjun
  0 siblings, 0 replies; 2+ messages in thread
From: Zhu Yanjun @ 2026-10-01 17:50 UTC (permalink / raw)
  To: Youngsung Ahn; +Cc: linux-rdma, stable

在 2026/10/1 8:24, Youngsung Ahn 写道:
> 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")
> Cc: stable@vger.kernel.org
> Signed-off-by: Youngsung Ahn <ays511.kr@gmail.com>
> Assisted-by: LLM
> ---
> Notes (not part of the commit):
> Reproduced on a KASAN x86-64 build of 7.3-rc4 as uid 1000. Present unchanged
> in mainline 551c722f4080 (2026-09-29) and rdma for-next. Compile-tested
> (KASAN+RDMA_RXE), not runtime-tested. Per security-bugs.rst this is public and
> a reproducer can be shared on request. IB_WR_REG_MR is the highest index the
> array initializes; an ARRAY_SIZE(rxe_wr_opcode_info) bound would be equivalent
> but the array is extern to this header.

The function wr_opcode_mask() is used in the following three functions:
"
validate_send_wr()
req_retry()
req_next_wqe()
"

In validate_send_wr() and req_next_wqe(), if wr_opcode_mask() returns 0, 
it is relatively clear from the surrounding code how the invalid opcode 
is handled.

However, for req_retry(), it is less clear to me what the subsequent 
control flow is when wr_opcode_mask() returns 0. In particular, I would 
like to understand whether returning 0 for an out-of-range opcode is 
sufficient to safely handle the invalid WQE in this path.

You mentioned that you were able to reproduce the issue on your local 
host. Would you be able to share the reproducer with us? It would help 
us better understand the failure path and verify the fix, especially for 
the req_retry() case.

Also, please follow Leon's advice and send v2 as a standalone patch.

Thanks a lot.
Yanjun Zhu

> 
> v2: no code change. The irregular indentation in v1 was email mangling (HTML),
> not a coding-style problem -- as Willy Tarreau noted on the ODP thread; resent
> as plain text with tabs preserved via git send-email. Added Cc: stable, fixed
> the author/Signed-off-by match, and added Assisted-by: LLM.
> 
>   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


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

end of thread, other threads:[~2026-10-01 17:50 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260930180221.2497908-1-ays511.kr@gmail.com>
2026-10-01 15:24 ` [PATCH v2] RDMA/rxe: bound the WQE opcode before indexing rxe_wr_opcode_info[] Youngsung Ahn
2026-10-01 17:50   ` Zhu Yanjun

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