diff options
| author | Tristan Madani <tristmd@gmail.com> | 2026-05-18 21:50:39 +0000 |
|---|---|---|
| committer | Jason Gunthorpe <jgg@nvidia.com> | 2026-05-29 20:32:48 -0300 |
| commit | 22b8fbded65b8c441b634a185f8da67657df6c50 (patch) | |
| tree | 3a871e0f19632677472f48279b376bfcc3cbc6dd | |
| parent | 3b6384dac14a306fd3d8e4357b5191a6f2b7f52e (diff) | |
| download | linux-stable-22b8fbded65b8c441b634a185f8da67657df6c50.tar.gz linux-stable-22b8fbded65b8c441b634a185f8da67657df6c50.zip | |
RDMA/rxe: Fix TOCTOU heap overflow in get_srq_wqe
get_srq_wqe() reads wqe->dma.num_sge from the shared receive queue
buffer, which is mapped into userspace. It validates num_sge against
max_sge, but then re-reads the same field to calculate the memcpy
size. A concurrent userspace thread can modify num_sge between
validation and use, causing a heap buffer overflow when copying the
WQE into qp->resp.srq_wqe.
Read num_sge into a local variable and use it for both the bounds
check and the size calculation.
Fixes: 8700e3e7c485 ("Soft RoCE driver")
Link: https://patch.msgid.link/r/20260518215040.1598586-2-tristan@talencesecurity.com
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
| -rw-r--r-- | drivers/infiniband/sw/rxe/rxe_resp.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index d8d1b7f2f341..29438bcde46f 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -264,6 +264,7 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) struct rxe_recv_wqe *wqe; struct ib_event ev; unsigned int count; + unsigned int num_sge; size_t size; unsigned long flags; @@ -279,12 +280,13 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) } /* don't trust user space data */ - if (unlikely(wqe->dma.num_sge > srq->rq.max_sge)) { + num_sge = wqe->dma.num_sge; + if (unlikely(num_sge > srq->rq.max_sge)) { spin_unlock_irqrestore(&srq->rq.consumer_lock, flags); rxe_dbg_qp(qp, "invalid num_sge in SRQ entry\n"); return RESPST_ERR_MALFORMED_WQE; } - size = sizeof(*wqe) + wqe->dma.num_sge*sizeof(struct rxe_sge); + size = sizeof(*wqe) + num_sge * sizeof(struct rxe_sge); memcpy(&qp->resp.srq_wqe, wqe, size); qp->resp.wqe = &qp->resp.srq_wqe.wqe; |
