mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
RDMA/rxe: Copy WQE to local buffer in non-SRQ receive path
For non-SRQ QPs, the responder reads WQE fields directly from the
shared queue buffer mapped into userspace. This allows a malicious
user to modify fields like num_sge or sge entries while the kernel
is processing the WQE, leading to out-of-bounds reads in
rxe_resp_check_length() and copy_data().
Introduce get_recv_wqe() that validates num_sge and copies the WQE
to a kernel-local buffer before processing, matching the approach
already used for SRQ WQEs in get_srq_wqe(). The srq_wqe buffer is
reused since SRQ and non-SRQ paths are mutually exclusive per QP.
Fixes: 8700e3e7c4 ("Soft RoCE driver")
Link: https://patch.msgid.link/r/20260518215040.1598586-3-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>
This commit is contained in:
parent
22b8fbded6
commit
d6ab440240
|
|
@ -310,6 +310,29 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)
|
|||
return RESPST_CHK_LENGTH;
|
||||
}
|
||||
|
||||
static enum resp_states rxe_get_recv_wqe(struct rxe_qp *qp)
|
||||
{
|
||||
struct rxe_queue *q = qp->rq.queue;
|
||||
struct rxe_recv_wqe *wqe;
|
||||
unsigned int num_sge;
|
||||
size_t size;
|
||||
|
||||
wqe = queue_head(q, QUEUE_TYPE_FROM_CLIENT);
|
||||
if (!wqe)
|
||||
return RESPST_ERR_RNR;
|
||||
|
||||
num_sge = wqe->dma.num_sge;
|
||||
if (unlikely(num_sge > qp->rq.max_sge)) {
|
||||
rxe_dbg_qp(qp, "invalid num_sge in recv WQE\n");
|
||||
return RESPST_ERR_MALFORMED_WQE;
|
||||
}
|
||||
size = sizeof(*wqe) + num_sge * sizeof(struct rxe_sge);
|
||||
memcpy(&qp->resp.srq_wqe, wqe, size);
|
||||
|
||||
qp->resp.wqe = &qp->resp.srq_wqe.wqe;
|
||||
return RESPST_CHK_LENGTH;
|
||||
}
|
||||
|
||||
static enum resp_states check_resource(struct rxe_qp *qp,
|
||||
struct rxe_pkt_info *pkt)
|
||||
{
|
||||
|
|
@ -330,9 +353,7 @@ static enum resp_states check_resource(struct rxe_qp *qp,
|
|||
if (srq)
|
||||
return get_srq_wqe(qp);
|
||||
|
||||
qp->resp.wqe = queue_head(qp->rq.queue,
|
||||
QUEUE_TYPE_FROM_CLIENT);
|
||||
return (qp->resp.wqe) ? RESPST_CHK_LENGTH : RESPST_ERR_RNR;
|
||||
return rxe_get_recv_wqe(qp);
|
||||
}
|
||||
|
||||
return RESPST_CHK_LENGTH;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user