mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
RDMA/rxe: Validate num_sge/cur_sge before indexing wqe->dma.sge[]
For a user QP, qp->sq.queue is a ring the application writes directly,
so rxe_post_send() takes the is_user branch and only schedules send_task
without validating the WQE. rxe_requester() consumes it in place via
req_next_wqe() and calls copy_data(), which indexes
&wqe->dma.sge[cur_sge] with the attacker-controlled num_sge/cur_sge.
Only the kernel path bounds num_sge (validate_send_wr()); the user WQE
is never checked, so a local unprivileged user can post a WQE with an
out-of-range cur_sge or oversized num_sge and force an out-of-bounds
read of the per-WQE sge array in copy_data() (vmalloc OOB read, local
DoS).
Bound num_sge to qp->sq.max_sge in rxe_requester() before use, the way
get_srq_wqe() already guards SRQ entries, and bound cur_sge only when
the WQE carries payload (dma.resid): copy_data() returns early on a
zero-length copy before touching dma->sge[], so a zero-payload WQE --
the only kind a max_sge == 0 QP can post -- stays valid.
Reproduced under KASAN; the vmalloc-out-of-bounds in copy_data() is gone.
Fixes: 8700e3e7c4 ("Soft RoCE driver")
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Link: https://patch.msgid.link/20260712122149.78142-1-security@auditcode.ai
Assisted-by: AuditCode-AI:2026.07
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
6f70142374
commit
126c757e4c
|
|
@ -701,6 +701,21 @@ int rxe_requester(struct rxe_qp *qp)
|
|||
if (unlikely(!wqe))
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Don't trust user space data: a user QP's WQE comes from an mmap'd
|
||||
* ring, so num_sge/cur_sge are attacker-controlled. Bound num_sge like
|
||||
* get_srq_wqe(); bound cur_sge only when payload exists (dma.resid),
|
||||
* since copy_data() skips dma->sge[] on a zero-length copy (all a
|
||||
* max_sge == 0 QP can post).
|
||||
*/
|
||||
if (unlikely(wqe->dma.num_sge > qp->sq.max_sge ||
|
||||
(wqe->dma.resid &&
|
||||
wqe->dma.cur_sge >= qp->sq.max_sge))) {
|
||||
rxe_dbg_qp(qp, "invalid num_sge/cur_sge in send wqe\n");
|
||||
wqe->status = IB_WC_LOC_QP_OP_ERR;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rxe_wqe_is_fenced(qp, wqe)) {
|
||||
qp->req.wait_fence = 1;
|
||||
goto exit;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user