diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index 5718c8bb28ac4..93322d20c0abf 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -296,6 +296,7 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) struct rxe_recv_wqe *wqe; struct ib_event ev; unsigned int count; + size_t size; if (srq->error) return RESPST_ERR_RNR; @@ -311,8 +312,13 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) return RESPST_ERR_RNR; } - /* note kernel and user space recv wqes have same size */ - memcpy(&qp->resp.srq_wqe, wqe, sizeof(qp->resp.srq_wqe)); + /* don't trust user space data */ + if (unlikely(wqe->dma.num_sge > srq->rq.max_sge)) { + pr_warn("%s: invalid num_sge in SRQ entry\n", __func__); + return RESPST_ERR_MALFORMED_WQE; + } + size = sizeof(wqe) + wqe->dma.num_sge*sizeof(struct rxe_sge); + memcpy(&qp->resp.srq_wqe, wqe, size); qp->resp.wqe = &qp->resp.srq_wqe.wqe; if (qp->is_user) {