From: sashiko-bot@kernel.org
To: "Tristan Madani" <tristmd@gmail.com>
Cc: linux-rdma@vger.kernel.org
Subject: Re: [PATCH v8 1/2] RDMA/rxe: copy send WQE to kernel buffer before processing
Date: Fri, 30 Oct 2026 17:04:30 +0000 [thread overview]
Message-ID: <sashiko-outbox-191303@kernel.org> (raw)
In-Reply-To: <20261030165044.2799619-2-tristan@talencesecurity.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] RDMA/rxe: broken atomic write resid check in req_next_wqe() allows OOB read
--
commit c2bf5201e4676c1f9f9acad4282470fc916075a3
Author: Tristan Madani <tristmd@gmail.com>
RDMA/rxe: copy send WQE to kernel buffer before processing
This commit copies send WQEs from the userspace-mapped send queue into a
kernel-private buffer in req_next_wqe() before processing, writing updated
fields back to the shared queue via rxe_req_writeback_wqe().
> diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
> index 4f353abd76f55..45e0e97d17926 100644
> --- a/drivers/infiniband/sw/rxe/rxe_req.c
> +++ b/drivers/infiniband/sw/rxe/rxe_req.c
[ ... ]
> @@ -193,7 +213,35 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
> }
> spin_unlock_irqrestore(&qp->state_lock, flags);
>
> - wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
> + /* Reuse the existing kernel-private copy if still valid */
> + if (qp->req.send_wqe_valid && qp->req.shared_wqe == wqe)
> + return &qp->req.send_wqe.wqe;
> +
> + /* Copy WQE from userspace-mapped shared queue to kernel-private
> + * buffer. Copy size matches the queue element data area.
> + */
> + memcpy(&qp->req.send_wqe, wqe, sizeof(*wqe) +
> + max_t(int, qp->sq.max_sge * sizeof(struct ib_sge),
> + qp->sq.max_inline));
> + qp->req.shared_wqe = wqe;
> + qp->req.send_wqe_valid = true;
> +
> + wqe = &qp->req.send_wqe.wqe;
> +
> + /* Prevent OOB in wr_opcode_mask() for corrupted opcodes.
> + * Mask 0 causes next_opcode() to fail, moving QP to error state.
> + */
> + if (unlikely(wqe->wr.opcode > IB_WR_REG_MR))
> + wqe->mask = 0;
> + else
> + wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
> +
> + /* Atomic writes carry exactly sizeof(u64) payload.
> + * Reject oversized resid to prevent OOB read in finish_packet().
> + */
> + if (unlikely((wqe->mask & RXE_ATOMIC_WRITE_MASK) &&
> + wqe->dma.resid > sizeof(u64)))
> + wqe->mask = 0;
> return wqe;
> }
[Severity: Critical]
Does this atomic write resid check in req_next_wqe() in
drivers/infiniband/sw/rxe/rxe_req.c actually reject an IB_WR_ATOMIC_WRITE WQE
posted with wqe->dma.resid > sizeof(u64), or can finish_packet() still read
out of bounds past qp->req.send_wqe?
First, wqe->mask is populated by wr_opcode_mask(), which returns flags from
enum rxe_wr_mask (bits 0..7, where WR_ATOMIC_WRITE_MASK is BIT(7)). Testing
wqe->mask against RXE_ATOMIC_WRITE_MASK from enum rxe_hdr_mask (BIT(27))
always evaluates to false.
Second, even if wqe->mask is set to 0, rxe_requester() and next_opcode() do
not reject a WQE based on wqe->mask == 0 when wqe->wr.opcode is
IB_WR_ATOMIC_WRITE. In rxe_requester():
if (wqe->mask & WR_LOCAL_OP_MASK) {
...
}
...
opcode = next_opcode(qp, wqe, wqe->wr.opcode);
if (unlikely(opcode < 0)) {
wqe->status = IB_WC_LOC_QP_OP_ERR;
goto err;
}
mask = rxe_opcode[opcode].mask;
next_opcode() -> next_opcode_rc() switches directly on wqe->wr.opcode without
checking wqe->mask:
case IB_WR_ATOMIC_WRITE:
return IB_OPCODE_RC_ATOMIC_WRITE;
rxe_requester() then sets mask and pkt.mask from rxe_opcode[opcode].mask
(which has RXE_ATOMIC_WRITE_MASK set), clamps payload to mtu (up to 4096
bytes), and calls finish_packet():
if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
memcpy(payload_addr(pkt), wqe->dma.atomic_wr, payload);
wqe->dma.resid -= payload;
}
Would this read up to 4096 bytes starting at
qp->req.send_wqe.wqe.dma.atomic_wr, reading past the 512-byte
qp->req.send_wqe.sge array into adjacent memory?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030165044.2799619-1-tristan@talencesecurity.com?part=1
next prev parent reply other threads:[~2026-10-30 17:04 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 16:50 [PATCH v8 0/2] RDMA/rxe: copy send WQE to kernel buffer before processing Tristan Madani
2026-10-30 16:50 ` [PATCH v8 1/2] " Tristan Madani
2026-10-30 17:04 ` sashiko-bot [this message]
2026-10-30 16:50 ` [PATCH v8 2/2] RDMA/rxe: copy send WQE to kernel buffer in completer path Tristan Madani
2026-10-30 17:13 ` sashiko-bot
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=sashiko-outbox-191303@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tristmd@gmail.com \
/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.