Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH v2] RDMA/rxe: Validate inline data range in user WQEs
@ 2026-09-26  7:04 Jiale Yao
  2026-09-26  7:15 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Jiale Yao @ 2026-09-26  7:04 UTC (permalink / raw)
  To: Zhu Yanjun, Jason Gunthorpe, Leon Romanovsky, Haggai Eran,
	Kamal Heib, Doug Ledford, Amir Vadai, Moni Shoua, linux-rdma,
	linux-kernel
  Cc: Jiale Yao

For a user QP, the send queue is an mmap'd ring which userspace writes
directly.  rxe_post_send() only schedules the send task for such a QP,
so userspace can also change WQE fields while rxe_requester() processes
the WQE.

Commit 126c757e4cd46f866ddc283143b58eb4d9bf52cd ("RDMA/rxe:
Validate num_sge/cur_sge before indexing wqe->dma.sge[]") added bounds
checks for two members of the userspace-controlled dma structure, but
left sge_offset unchecked.  For an inline WQE, finish_packet() uses that
value directly as an index into inline_data[] and copies dma.resid bytes
from the resulting pointer into the packet payload.

A local user with access to uverbs can therefore put an out-of-range
sge_offset in the mmap'd SQ ring.  This can disclose kernel memory in the
outgoing packet or cause a vmalloc out-of-bounds access.

Since sge_offset comes from shared memory, validating it in
rxe_requester() and then reading it again in finish_packet() leaves a
TOCTOU window.  Copy it into a local variable in finish_packet(), validate
that local value, and use the same value for the copy and update.  Check
the offset first and use subtraction for the length check to avoid an
integer overflow.

I reproduced this on Linux 7.3-rc4 with an RC user QP, IB_SEND_INLINE,
a 64-byte residual length, and sge_offset set to 0x100000.  KASAN
reported:

  BUG: KASAN: vmalloc-out-of-bounds in rxe_requester+0x1f27/0x4940
  Read of size 64 at addr ffffc90000191250 by task kworker/u16:0/12
  Workqueue: rxe_wq do_work
  Call Trace:
   __asan_memcpy
   rxe_requester+0x1f27/0x4940
   rxe_sender+0xe/0x30
   do_work+0x184/0x3d0
   process_scheduled_works+0x7c0/0xf10

Fixes: 8700e3e7c485 ("Soft RoCE driver")
Link: https://lore.kernel.org/all/20260708224534.1206-1-security@auditcode.ai/
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
V1 -> V2: Copy sge_offset from the shared WQE into a local variable in
  finish_packet(), validate that local value, and reuse it for the memcpy
  and update. This closes the TOCTOU race reported by Sashiko.

 drivers/infiniband/sw/rxe/rxe_req.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
index 24f5c044363f..f7e59805a664 100644
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -503,6 +503,7 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_av *av,
 			 struct sk_buff *skb, u32 payload)
 {
 	int err;
+	u32 sge_offset;
 
 	err = rxe_prepare(av, pkt, skb);
 	if (err)
@@ -510,12 +511,19 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_av *av,
 
 	if (pkt->mask & RXE_WRITE_OR_SEND_MASK) {
 		if (wqe->wr.send_flags & IB_SEND_INLINE) {
-			u8 *tmp = &wqe->dma.inline_data[wqe->dma.sge_offset];
+			sge_offset = wqe->dma.sge_offset;
+			if (unlikely(sge_offset > qp->sq.max_inline ||
+				     payload >
+				     qp->sq.max_inline - sge_offset)) {
+				rxe_dbg_qp(qp, "invalid inline data range in send wqe\n");
+				return -EINVAL;
+			}
 
-			memcpy(payload_addr(pkt), tmp, payload);
+			memcpy(payload_addr(pkt),
+			       &wqe->dma.inline_data[sge_offset], payload);
 
 			wqe->dma.resid -= payload;
-			wqe->dma.sge_offset += payload;
+			wqe->dma.sge_offset = sge_offset + payload;
 		} else {
 			err = copy_data(qp->pd, 0, &wqe->dma,
 					payload_addr(pkt), payload,
-- 
2.34.1


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

* Re: [PATCH v2] RDMA/rxe: Validate inline data range in user WQEs
  2026-09-26  7:04 [PATCH v2] RDMA/rxe: Validate inline data range in user WQEs Jiale Yao
@ 2026-09-26  7:15 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-09-26  7:15 UTC (permalink / raw)
  To: Jiale Yao; +Cc: linux-rdma

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] RDMA/rxe: incomplete TOCTOU fix due to missing READ_ONCE()
--

commit e7e4b53005e1e5706321c684271dff347a0b85b9
Author: Jiale Yao <yaojiale02@163.com>

RDMA/rxe: Validate inline data range in user WQEs

This commit addresses a vulnerability where userspace can provide an
out-of-bounds sge_offset for an inline WQE in the mmap'd send queue ring.
It validates the offset and copies it to a local variable to prevent a
TOCTOU race.

Link: https://lore.kernel.org/all/20260708224534.1206-1-security@auditcode.ai/

> diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
> index 53f7c1e7fe55b..fd2f248a1f448 100644
> --- a/drivers/infiniband/sw/rxe/rxe_req.c
> +++ b/drivers/infiniband/sw/rxe/rxe_req.c

[ ... ]

> @@ -510,12 +511,19 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_av *av,
>  
>  	if (pkt->mask & RXE_WRITE_OR_SEND_MASK) {
>  		if (wqe->wr.send_flags & IB_SEND_INLINE) {
> -			u8 *tmp = &wqe->dma.inline_data[wqe->dma.sge_offset];
> +			sge_offset = wqe->dma.sge_offset;
> +			if (unlikely(sge_offset > qp->sq.max_inline ||
> +				     payload >
> +				     qp->sq.max_inline - sge_offset)) {
> +				rxe_dbg_qp(qp, "invalid inline data range in send wqe\n");
> +				return -EINVAL;
> +			}
>  
> -			memcpy(payload_addr(pkt), tmp, payload);
> +			memcpy(payload_addr(pkt),
> +			       &wqe->dma.inline_data[sge_offset], payload);

[Severity: High]
Does this code still leave a TOCTOU window open?

In drivers/infiniband/sw/rxe/rxe_req.c:finish_packet(), the value of
wqe->dma.sge_offset is read from shared memory into the local variable
sge_offset using a standard assignment.

Without a READ_ONCE() wrapper, the compiler is free to optimize out the local
variable and emit multiple memory loads directly from the shared memory
pointer. If a local attacker modifies the mmap'd wqe->dma.sge_offset value
concurrently after the bounds check but before the memcpy executes, the
compiler might reload the modified value for the memcpy indexing.

Could this regression result in an out-of-bounds kernel memory read,
leading to sensitive information disclosure or a KASAN vmalloc-out-of-bounds
panic?

>  
>  			wqe->dma.resid -= payload;
> -			wqe->dma.sge_offset += payload;
> +			wqe->dma.sge_offset = sge_offset + payload;
>  		} else {

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260926070403.3005250-1-yaojiale02@163.com?part=1

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

end of thread, other threads:[~2026-09-26  7:15 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-26  7:04 [PATCH v2] RDMA/rxe: Validate inline data range in user WQEs Jiale Yao
2026-09-26  7:15 ` sashiko-bot

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