From: Yishai Hadas <yishaih@nvidia.com>
To: <jgg@ziepe.ca>, <leon@kernel.org>
Cc: <linux-rdma@vger.kernel.org>, <netdev@vger.kernel.org>,
<saeedm@nvidia.com>, <tariqt@nvidia.com>, <mbloch@nvidia.com>,
<kuba@kernel.org>, <pabeni@redhat.com>, <edumazet@kernel.org>,
<davem@davemloft.net>, <andrew+netdev@lunn.ch>,
<dtatulea@nvidia.com>, <moshe@nvidia.com>, <yishaih@nvidia.com>,
<maorg@nvidia.com>
Subject: [PATCH V1 rdma-next 22/24] RDMA/mlx5: Clamp log_max_* shifts in query_device and ucontext paths
Date: Tue, 10 Nov 2026 15:43:18 +0200 [thread overview]
Message-ID: <20261110134320.34408-23-yishaih@nvidia.com> (raw)
In-Reply-To: <20261110134320.34408-1-yishaih@nvidia.com>
The device, port and ucontext attributes and the SRQ size limit are
computed as 1 << cap from log_max_* FW capabilities. An untrusted NIC
can report 31 or more, which makes the shift undefined. The same
applies to 1ull << log_pg_sz with a value of 64 or more, and to the
max_tso computed as 1 << max_lso_cap, which can be 31.
Use MLX5_CAP_GEN_LOGSZ_U32() and MLX5_CAP_GEN_LOGSZ_U64() for these
values, and BIT() for max_tso. As the limits can now reach 2^31,
compute max_qp_wr in 64 bits and saturate the max_res_rd_atom and
max_total_mcast_qp_attach products at U32_MAX. Cap max_cqe at 2^30 - 1,
the largest CQ size the create path accepts.
The SRQ size limit then lets the rounded up SRQ size overflow the int
srq->msrq.max, and the SRQ buffer size exceed the int passed to
create_srq_user() and create_srq_kernel(). Reject both above INT_MAX,
computing the buffer size with check_mul_overflow().
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
---
drivers/infiniband/hw/mlx5/mad.c | 2 +-
drivers/infiniband/hw/mlx5/main.c | 65 +++++++++++++++++--------------
drivers/infiniband/hw/mlx5/srq.c | 14 +++++--
3 files changed, 46 insertions(+), 35 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c
index 8925331855ff..cf9f6a4d5ccf 100644
--- a/drivers/infiniband/hw/mlx5/mad.c
+++ b/drivers/infiniband/hw/mlx5/mad.c
@@ -629,7 +629,7 @@ int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u32 port,
props->phys_state = out_mad->data[33] >> 4;
props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20));
props->gid_tbl_len = out_mad->data[50];
- props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
+ props->max_msg_sz = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_msg);
props->pkey_tbl_len = dev->pkey_table_len;
props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46));
props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48));
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 808c66c7afb3..df42a04799ec 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -599,7 +599,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u32 port_num,
props->qkey_viol_cntr = qkey_viol_cntr;
}
props->max_mtu = IB_MTU_4096;
- props->max_msg_sz = 1 << MLX5_CAP_GEN(dev->mdev, log_max_msg);
+ props->max_msg_sz = MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_msg);
props->pkey_tbl_len = 1;
props->state = IB_PORT_DOWN;
props->phys_state = IB_PORT_PHYS_STATE_DISABLED;
@@ -930,7 +930,7 @@ static u32 mlx5_ib_calc_max_sq_overhead(void)
static u32 mlx5_ib_calc_max_qp_wr(struct mlx5_ib_dev *dev)
{
struct mlx5_core_dev *mdev = dev->mdev;
- u32 max_wqe_bb_units = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
+ u64 max_wqe_bb_units = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_qp_sz);
u32 max_wqe_size;
/* max QP overhead + 1 SGE, no inline, no special features */
max_wqe_size = mlx5_ib_calc_max_sq_overhead() +
@@ -940,7 +940,8 @@ static u32 mlx5_ib_calc_max_qp_wr(struct mlx5_ib_dev *dev)
max_wqe_size = ALIGN(max_wqe_size, MLX5_SEND_WQE_BB);
- return (max_wqe_bb_units * MLX5_SEND_WQE_BB) / max_wqe_size;
+ /* Up to 2^31 units, so the product needs 64 bits */
+ return div_u64(max_wqe_bb_units * MLX5_SEND_WQE_BB, max_wqe_size);
}
static int mlx5_ib_query_device(struct ib_device *ibdev,
@@ -954,7 +955,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
int max_sq_desc;
int max_rq_sg;
int max_sq_sg;
- u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);
+ u64 min_page_size = MLX5_CAP_GEN_LOGSZ_U64(mdev, log_pg_sz);
bool raw_support = !mlx5_core_mp_enabled(mdev);
struct mlx5_ib_query_device_resp resp = {};
size_t resp_len;
@@ -1000,7 +1001,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
if (MLX5_CAP_GEN(mdev, imaicl)) {
props->device_cap_flags |= IB_DEVICE_MEM_WINDOW |
IB_DEVICE_MEM_WINDOW_TYPE_2B;
- props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
+ props->max_mw = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_mkey);
/* We support 'Gappy' memory registration too */
props->kernel_cap_flags |= IBK_SG_GAPS_REG;
}
@@ -1033,7 +1034,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
if (offsetofend(typeof(resp), tso_caps) <= uhw_outlen) {
max_tso = MLX5_CAP_ETH(mdev, max_lso_cap);
if (max_tso) {
- resp.tso_caps.max_tso = 1 << max_tso;
+ resp.tso_caps.max_tso = BIT(max_tso);
resp.tso_caps.supported_qpts |=
1 << IB_QPT_RAW_PACKET;
resp.response_length += sizeof(resp.tso_caps);
@@ -1100,7 +1101,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
props->max_mr_size = ~0ull;
props->page_size_cap = ~(min_page_size - 1);
- props->max_qp = 1 << MLX5_CAP_GEN(mdev, log_max_qp);
+ props->max_qp = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_qp);
props->max_qp_wr = mlx5_ib_calc_max_qp_wr(dev);
max_rq_sg = MLX5_CAP_GEN(mdev, max_wqe_sz_rq) /
sizeof(struct mlx5_wqe_data_seg);
@@ -1111,29 +1112,33 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
props->max_send_sge = max_sq_sg;
props->max_recv_sge = max_rq_sg;
props->max_sge_rd = MLX5_MAX_SGE_RD;
- props->max_cq = 1 << MLX5_CAP_GEN(mdev, log_max_cq);
- props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_cq_sz)) - 1;
- props->max_mr = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
- props->max_pd = 1 << MLX5_CAP_GEN(mdev, log_max_pd);
- props->max_qp_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_req_qp);
- props->max_qp_init_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_res_qp);
- props->max_srq = 1 << MLX5_CAP_GEN(mdev, log_max_srq);
- props->max_srq_wr = (1 << MLX5_CAP_GEN(mdev, log_max_srq_sz)) - 1;
+ props->max_cq = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_cq);
+ /* The CQ size is a power of two that fits in an int */
+ props->max_cqe = min_t(u32, MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_cq_sz),
+ rounddown_pow_of_two(INT_MAX)) - 1;
+ props->max_mr = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_mkey);
+ props->max_pd = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_pd);
+ props->max_qp_rd_atom = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_ra_req_qp);
+ props->max_qp_init_rd_atom = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_ra_res_qp);
+ props->max_srq = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_srq);
+ props->max_srq_wr = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_srq_sz) - 1;
props->local_ca_ack_delay = MLX5_CAP_GEN(mdev, local_ca_ack_delay);
- props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
+ props->max_res_rd_atom = min_t(u64, (u64)props->max_qp_rd_atom * props->max_qp,
+ U32_MAX);
props->max_srq_sge = max_rq_sg - 1;
props->max_fast_reg_page_list_len =
- 1 << MLX5_CAP_GEN(mdev, log_max_klm_list_size);
+ MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_klm_list_size);
props->max_pi_fast_reg_page_list_len =
props->max_fast_reg_page_list_len / 2;
props->max_sgl_rd =
MLX5_CAP_GEN(mdev, max_sgl_for_optimized_performance);
get_atomic_caps_qp(dev, props);
props->masked_atomic_cap = IB_ATOMIC_NONE;
- props->max_mcast_grp = 1 << MLX5_CAP_GEN(mdev, log_max_mcg);
+ props->max_mcast_grp = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_mcg);
props->max_mcast_qp_attach = MLX5_CAP_GEN(mdev, max_qp_mcg);
- props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
- props->max_mcast_grp;
+ props->max_total_mcast_qp_attach =
+ min_t(u64, (u64)props->max_mcast_qp_attach * props->max_mcast_grp,
+ U32_MAX);
props->max_ah = INT_MAX;
props->hca_core_clock = MLX5_CAP_GEN(mdev, device_frequency_khz);
props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
@@ -1167,19 +1172,19 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
if (mlx5_ib_port_link_layer(ibdev, 1) ==
IB_LINK_LAYER_ETHERNET && raw_support) {
props->rss_caps.max_rwq_indirection_tables =
- 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt);
+ MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_rqt);
props->rss_caps.max_rwq_indirection_table_size =
- 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt_size);
+ MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_rqt_size);
props->rss_caps.supported_qpts = 1 << IB_QPT_RAW_PACKET;
props->max_wq_type_rq =
- 1 << MLX5_CAP_GEN(dev->mdev, log_max_rq);
+ MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_rq);
}
if (MLX5_CAP_GEN(mdev, tag_matching)) {
props->tm_caps.max_num_tags =
- (1 << MLX5_CAP_GEN(mdev, log_tag_matching_list_sz)) - 1;
+ MLX5_CAP_GEN_LOGSZ_U32(mdev, log_tag_matching_list_sz) - 1;
props->tm_caps.max_ops =
- 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
+ MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_qp_sz);
props->tm_caps.max_sge = MLX5_TM_MAX_SGE;
}
@@ -1503,7 +1508,7 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u32 port,
props->port_cap_flags &= ~IB_PORT_CM_SUP;
props->gid_tbl_len = mlx5_get_gid_table_len(MLX5_CAP_GEN(mdev, gid_table_size));
- props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
+ props->max_msg_sz = MLX5_CAP_GEN_LOGSZ_U32(mdev, log_max_msg);
props->pkey_tbl_len = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev, pkey_table_size));
props->bad_pkey_cntr = rep->pkey_violation_counter;
props->qkey_viol_cntr = rep->qkey_violation_counter;
@@ -2127,16 +2132,16 @@ static int set_ucontext_resp(struct ib_ucontext *uctx,
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY;
}
- resp->qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
+ resp->qp_tab_size = MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_qp);
if (mlx5_wc_support_get(dev->mdev))
resp->bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev,
log_bf_reg_size);
resp->cache_line_size = cache_line_size();
resp->max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
resp->max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
- resp->max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
- resp->max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
- resp->max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);
+ resp->max_send_wqebb = MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_qp_sz);
+ resp->max_recv_wr = MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_qp_sz);
+ resp->max_srq_recv_wr = MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_srq_sz);
resp->cqe_version = context->cqe_version;
resp->log_uar_size = MLX5_CAP_GEN(dev->mdev, uar_4k) ?
MLX5_ADAPTER_PAGE_SHIFT : PAGE_SHIFT;
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
index 6a4a937d97ce..4bd04599d98f 100644
--- a/drivers/infiniband/hw/mlx5/srq.c
+++ b/drivers/infiniband/hw/mlx5/srq.c
@@ -196,9 +196,10 @@ int mlx5_ib_create_srq(struct ib_srq *ib_srq,
struct mlx5_ib_srq *srq = to_msrq(ib_srq);
size_t desc_size;
size_t buf_size;
+ unsigned long max;
int err;
struct mlx5_srq_attr in = {};
- __u32 max_srq_wqes = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);
+ __u32 max_srq_wqes = MLX5_CAP_GEN_LOGSZ_U32(dev->mdev, log_max_srq_sz);
__u32 max_sge_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq) /
sizeof(struct mlx5_wqe_data_seg);
@@ -222,7 +223,11 @@ int mlx5_ib_create_srq(struct ib_srq *ib_srq,
mutex_init(&srq->mutex);
spin_lock_init(&srq->lock);
- srq->msrq.max = roundup_pow_of_two(init_attr->attr.max_wr + 1);
+ /* srq->msrq.max is an int */
+ max = roundup_pow_of_two(init_attr->attr.max_wr + 1);
+ if (max > INT_MAX)
+ return -EINVAL;
+ srq->msrq.max = max;
srq->msrq.max_gs = init_attr->attr.max_sge;
desc_size = sizeof(struct mlx5_wqe_srq_next_seg) +
@@ -238,8 +243,9 @@ int mlx5_ib_create_srq(struct ib_srq *ib_srq,
srq->msrq.max_avail_gather = (desc_size - sizeof(struct mlx5_wqe_srq_next_seg)) /
sizeof(struct mlx5_wqe_data_seg);
srq->msrq.wqe_shift = ilog2(desc_size);
- buf_size = srq->msrq.max * desc_size;
- if (buf_size < desc_size)
+ /* create_srq_user() and create_srq_kernel() take an int */
+ if (check_mul_overflow((size_t)srq->msrq.max, desc_size, &buf_size) ||
+ buf_size > INT_MAX)
return -EINVAL;
in.type = init_attr->srq_type;
--
2.18.1
next prev parent reply other threads:[~2026-11-10 13:45 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 13:42 [PATCH V1 rdma-next 00/24] mlx5: Adversarial mode for confidential computing guests Yishai Hadas
2026-11-10 13:42 ` [PATCH V1 rdma-next 01/24] net/mlx5: Add mlx5_trigger_health_work_force() Yishai Hadas
2026-11-10 13:42 ` [PATCH V1 rdma-next 02/24] net/mlx5: Derive adversarial mode from CC guest memory encryption Yishai Hadas
2026-11-10 13:42 ` [PATCH V1 rdma-next 03/24] net/mlx5: Add capability filtering in adversarial mode Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 04/24] net/mlx5: Catch too low max number of EQs Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 05/24] net/mlx5: Add macros for reading log-based caps Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 06/24] RDMA/mlx5: Reject QP transport types not enabled by FW capability Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 07/24] RDMA/mlx5: Require IB_QPT_DRIVER for the DC vendor QP types Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 08/24] RDMA/mlx5: Derive mlx5_ib_adversarial_mode global from mlx5_core adversarial API Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 09/24] RDMA/core: Suppress kverbs_provider for adversarial_mode devices Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 10/24] RDMA/mlx5: Remove duplicate mlx5_ib_umr_context struct Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 11/24] RDMA/mlx5: Introduce per-CQ poll_one hook in mlx5_ib_cq Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 12/24] RDMA/mlx5: Add shadow FIFO infrastructure for UMR completions Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 13/24] RDMA/mlx5: Verify UMR CQ polling against a hostile NIC Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 14/24] RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 15/24] RDMA/mlx5: Block generic CQ poll path in adversarial mode Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 16/24] RDMA/core: Set the CQ comp_handler after its poll context is set up Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 17/24] RDMA/mlx5: Ignore completion events for a kernel CQ that is not ready Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 18/24] RDMA/mlx5: Validate EQE port and GSI port before indexing devr.ports[] Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 19/24] RDMA/mlx5: Validate firmware RQ/SQ state before sqrq_trans[] lookup Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 20/24] RDMA/mlx5: Clamp log_max_cq_sz shift in CQ size checks Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 21/24] RDMA/mlx5: Clamp log_max_* shifts in QP and WQ limit checks Yishai Hadas
2026-11-10 13:43 ` Yishai Hadas [this message]
2026-11-10 13:43 ` [PATCH V1 rdma-next 23/24] RDMA/core: Report and enforce adversarial mode via GET_CONTEXT Yishai Hadas
2026-11-10 13:43 ` [PATCH V1 rdma-next 24/24] RDMA/mlx5: Advertise adversarial mode via ib_device::adversarial_mode Yishai Hadas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110134320.34408-23-yishaih@nvidia.com \
--to=yishaih@nvidia.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=dtatulea@nvidia.com \
--cc=edumazet@kernel.org \
--cc=jgg@ziepe.ca \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=maorg@nvidia.com \
--cc=mbloch@nvidia.com \
--cc=moshe@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=saeedm@nvidia.com \
--cc=tariqt@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox