mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
RDMA/mlx5: Fix integer overflow of user QP buffer size
set_user_buf_size() computes the QP buffer size by left-shifting the
user-supplied rq.wqe_cnt and rq.wqe_shift values as signed integers.
A sufficiently large rq.wqe_cnt causes signed integer overflow, which
is undefined behavior, and yields a small or negative buf_size, causing
ib_umem_get() to map a buffer smaller than the hardware will actually
write into.
Replace the shifts and addition with check_shl_overflow() and
check_add_overflow(), rejecting invalid user inputs.
Moreover, guard the identical shift computing qp->sq.offset in
_create_user_qp() before set_user_buf_size() is reached.
Fixes: e126ba97db ("mlx5: Add driver for Mellanox Connect-IB adapters")
Signed-off-by: Maher Sanalla <msanalla@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
Link: https://patch.msgid.link/20260723-fix-qp-buf-size-overflow-v1-1-ccb05ee43a7b@nvidia.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
0087470661
commit
dec47e4b0f
|
|
@ -647,6 +647,7 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,
|
|||
struct ib_qp_init_attr *attr)
|
||||
{
|
||||
int desc_sz = 1 << qp->sq.wqe_shift;
|
||||
int rq_buf_size, sq_buf_size;
|
||||
|
||||
if (desc_sz > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)) {
|
||||
mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n",
|
||||
|
|
@ -671,11 +672,21 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,
|
|||
|
||||
if (attr->qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & IB_QP_CREATE_SOURCE_QPN) {
|
||||
base->ubuffer.buf_size = qp->rq.wqe_cnt << qp->rq.wqe_shift;
|
||||
qp->raw_packet_qp.sq.ubuffer.buf_size = qp->sq.wqe_cnt << 6;
|
||||
if (check_shl_overflow(qp->rq.wqe_cnt, qp->rq.wqe_shift,
|
||||
&base->ubuffer.buf_size))
|
||||
return -EINVAL;
|
||||
if (check_shl_overflow(qp->sq.wqe_cnt, 6,
|
||||
&qp->raw_packet_qp.sq.ubuffer.buf_size))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
base->ubuffer.buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
|
||||
(qp->sq.wqe_cnt << 6);
|
||||
if (check_shl_overflow(qp->rq.wqe_cnt, qp->rq.wqe_shift,
|
||||
&rq_buf_size))
|
||||
return -EINVAL;
|
||||
if (check_shl_overflow(qp->sq.wqe_cnt, 6, &sq_buf_size))
|
||||
return -EINVAL;
|
||||
if (check_add_overflow(rq_buf_size, sq_buf_size,
|
||||
&base->ubuffer.buf_size))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1004,7 +1015,11 @@ static int _create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
|
|||
|
||||
qp->rq.offset = 0;
|
||||
qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
|
||||
qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
|
||||
if (check_shl_overflow(qp->rq.wqe_cnt, qp->rq.wqe_shift,
|
||||
&qp->sq.offset)) {
|
||||
err = -EINVAL;
|
||||
goto err_bfreg;
|
||||
}
|
||||
|
||||
err = set_user_buf_size(dev, qp, ucmd, base, attr);
|
||||
if (err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user