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 rdma-next 03/23] net/mlx5: Add capability filtering in adversarial mode
Date: Tue, 3 Nov 2026 18:39:29 +0200 [thread overview]
Message-ID: <20261103163949.1554-4-yishaih@nvidia.com> (raw)
In-Reply-To: <20261103163949.1554-1-yishaih@nvidia.com>
From: Dragos Tatulea <dtatulea@nvidia.com>
When in adversarial mode, trust only a subset of capabilities
and do some additional validations.
Start off by clearing all firmware capabilities and enabling
them one by one. Some numeric capabilities are validated.
Unexpected values will trigger a driver load failure flow.
Where it applies, the filtering is done on both current and max caps.
Allowed capabilities are simply passed through. Clamped and checked
capabilities also apply to max values.
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Yishai Hadas <yishaih@nvidia.com>
Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
.../ethernet/mellanox/mlx5/core/caps_filter.c | 381 ++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/main.c | 8 +-
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +
4 files changed, 388 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/caps_filter.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index a1871259210d..dc8eabee631f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_MLX5_CORE) += mlx5_core.o
#
# mlx5 core basic
#
-mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
+mlx5_core-y := main.o caps_filter.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
health.o mcg.o cq.o alloc.o port.o mr.o pd.o \
transobj.o vport.o sriov.o fs_cmd.o fs_core.o pci_irq.o \
fs_counters.o fs_ft_pool.o rl.o lag/debugfs.o lag/lag.o dev.o events.o wq.o lib/gid.o \
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/caps_filter.c b/drivers/net/ethernet/mellanox/mlx5/core/caps_filter.c
new file mode 100644
index 000000000000..67b260339745
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/caps_filter.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include "linux/mlx5/device.h"
+#include <linux/mlx5/driver.h>
+#include <linux/mlx5/qp.h>
+#include "mlx5_core.h"
+
+#define MLX5_HCA_CAP_ALLOW(cap, fld) \
+ MLX5_SET(cap, dst, fld, MLX5_GET(cap, src, fld))
+#define MLX5_HCA_CAP_ALLOW64(cap, fld) \
+ MLX5_SET64(cap, dst, fld, MLX5_GET64(cap, src, fld))
+
+/* Allow a numeric capability range restricted to [lo, hi]. */
+#define MLX5_HCA_CAP_CLAMP(cap, fld, lo, hi) \
+ MLX5_SET(cap, dst, fld, mlx5_cap_clamp(dev, #fld, \
+ MLX5_GET(cap, src, fld), \
+ (lo), (hi)))
+
+/* Check cap range and return error otherwise. */
+#define MLX5_HCA_CAP_CHECK(cap, fld, lo, hi) \
+ mlx5_cap_check(dev, #fld, MLX5_GET(cap, dst, fld), (lo), (hi), false)
+/* Same but zero is also a valid value. */
+#define MLX5_HCA_CAP_CHECK_Z(cap, fld, lo, hi) \
+ mlx5_cap_check(dev, #fld, MLX5_GET(cap, dst, fld), (lo), (hi), true)
+
+static u32 mlx5_cap_clamp(struct mlx5_core_dev *dev, const char *name,
+ u32 val, u32 lo, u32 hi)
+{
+ u32 clamped = clamp_t(u32, val, lo, hi);
+
+ if (clamped != val)
+ mlx5_core_warn(dev, "cap filter: FW reported %s=%u, outside [%u, %u], using %u\n",
+ name, val, lo, hi, clamped);
+
+ return clamped;
+}
+
+static int mlx5_cap_check(struct mlx5_core_dev *dev, const char *name,
+ u32 val, u32 lo, u32 hi, bool zero)
+{
+ if (val >= lo && val <= hi)
+ return 0;
+
+ if (zero && !val)
+ return 0;
+
+ mlx5_core_err(dev, "cap filter: FW reported %s=%u, outside [%u, %u] %s\n",
+ name, val, lo, hi,
+ zero ? "or 0" : "");
+
+ return -EINVAL;
+}
+
+static int mlx5_adversarial_filter_general(struct mlx5_core_dev *dev, void *dst,
+ void *src)
+{
+ int err;
+
+ memset(dst, 0, MLX5_UN_SZ_BYTES(hca_cap_union));
+
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, page_request_disable);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vhca_resource_manager);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, hca_cap_2);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, event_on_vhca_state_teardown_request);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, event_on_vhca_state_in_use);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, event_on_vhca_state_active);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, event_on_vhca_state_allocated);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, event_on_vhca_state_invalid);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vhca_id);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_srq_sz);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_qp_sz);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, event_cap);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_qp);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_srq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_sgl_for_optimized_performance);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_cq_sz);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, relaxed_ordering_write_umr);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, relaxed_ordering_read_umr);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_cq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, relaxed_ordering_write);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, relaxed_ordering_read_pci_enabled);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_mkey);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, terminate_scatter_list_mkey);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, fast_teardown);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_eq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_indirection);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, fixed_buffer_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, force_teardown);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, umr_extended_translation_offset);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_klm_list_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, qpc_extension);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_ra_req_dc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vnic_env_cq_overrun);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_ra_res_dc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, release_all_pages);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, roce_accl);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_ra_req_qp);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_ra_res_qp);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, end_pad);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cc_query_allowed);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cc_modify_allowed);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cache_line_128byte);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, rts2rts_qp_counters_set_id);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vnic_env_int_rq_oob);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, sbcam_reg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, qcam_reg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, gid_table_size);
+
+ /* Values outside of [0, 4] range are unexpected. */
+ err = MLX5_HCA_CAP_CHECK(cmd_hca_cap, gid_table_size, 0, 4);
+ if (err)
+ return err;
+
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, out_of_seq_cnt);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vport_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, retransmission_q_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, debug);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, modify_rq_counter_set_id);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, rq_delay_drop);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_qp_cnt);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, pkey_table_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vport_group_manager);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vnic_env_queue_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, ets);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, nic_flow_table);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, mcam_reg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, pcam_reg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, local_ca_ack_delay);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, enhanced_error_q_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, beacon_led);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, port_type);
+ /* 0 is invalid, 8 is for MLX5_MAX_PORTS */
+ MLX5_HCA_CAP_CLAMP(cmd_hca_cap, num_ports, 1, 8);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_msg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_tc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, dcbx);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, general_notification_event);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, stat_rate_support);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, pci_sync_for_fw_update_event);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cqe_version);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, umr_modify_entity_size_disabled);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, umr_modify_atomic_disabled);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, umr_indirect_mkey_disabled);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, umr_fence);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cmdif_checksum);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, sho);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, qos);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, eth_net_offloads);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, roce);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, atomic);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cq_moderation);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cq_period_mode_modify);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cq_period_start_from_cqe);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, apm);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, umr_ptr_rlky);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, qp_packet_based);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, pkv);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, rc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, uar_4k);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, fl_rc_qp_when_roce_disabled);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_pg_sz);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, bf);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, driver_version);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, mkey_by_name);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_bf_reg_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, disciplined_fr_counter);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, qp_error_syndrome);
+ MLX5_HCA_CAP_CLAMP(cmd_hca_cap, num_lag_ports, 0, 1);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_wqe_sz_sq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, icm_mng_function_id_mode);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, tis_tir_td_order);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_wqe_sz_rq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, query_host_net_function_num_max);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_qp_mcg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_mcg);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_transport_domain);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, relaxed_ordering_read);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_pd);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, dp_ordering_ooo_all_ud);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, dp_ordering_ooo_all_uc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, dp_ordering_ooo_all_xrc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, dp_ordering_ooo_all_dc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, dp_ordering_ooo_all_rc);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, pcie_reset_using_hotreset_method);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap,
+ pci_sync_for_fw_update_with_driver_unload);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vnic_env_cnt_steering_fail);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vport_counter_local_loopback);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, q_counter_aggregation);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, q_counter_other_vport);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, nic_receive_steering_discard);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, receive_discard_vport_down);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, transmit_discard_vport_down);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, eq_overrun_count);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, invalid_command_count);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, quota_exceeded_count);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_flow_counter_bulk);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_rq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_sq);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_tir);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, basic_cyclic_rcv_wqe);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_rqt);
+ MLX5_HCA_CAP_CLAMP(cmd_hca_cap, log_max_rqt_size, 0, 13);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vnic_env_cnt_bar_uar_access);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vnic_env_cnt_odp_page_fault);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, roce_rw_supported);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_wq_sz);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, vhca_state);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_vlan_list);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_current_mc_list);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_current_uc_list);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, sq_ts_format);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, rq_ts_format);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, steering_format_version);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, create_qp_start_hint);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, ats);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, cross_vhca_rqt);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_uctx);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_num_eqs);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_uar_page_sz);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_geneve_tlv_options);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_geneve_tlv_option_data_len);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_dci_stream_channels);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, log_max_dci_errored_streams);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, crossing_vhca_mkey);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, native_port_num);
+ MLX5_HCA_CAP_CLAMP(cmd_hca_cap, num_vhca_ports, 0, 1);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, sw_owner_id);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_num_of_monitor_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, num_ppcnt_monitor_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, num_q_monitor_counters);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, apu);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, uctx_cap);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, num_total_dynamic_vf_msix);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, min_dynamic_vf_msix_table_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, data_direct);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, max_dynamic_vf_msix_table_size);
+ MLX5_HCA_CAP_ALLOW64(cmd_hca_cap, vhca_tunnel_commands);
+
+ MLX5_SET(cmd_hca_cap, dst, num_of_uars_per_page, MLX5_UARS_IN_PAGE);
+
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap, flow_counter_bulk_alloc);
+
+ err = MLX5_HCA_CAP_CHECK(cmd_hca_cap, log_pg_sz,
+ MLX5_ADAPTER_PAGE_SHIFT,
+ MLX5_ADAPTER_PAGE_SHIFT);
+ if (err)
+ return err;
+
+#define LOG_BF_REG_SIZE_MIN ilog2(2 * MLX5_SEND_WQE_BB)
+#define LOG_BF_REG_SIZE_MAX \
+ ilog2((MLX5_ADAPTER_PAGE_SIZE - MLX5_BF_OFFSET) / MLX5_BFREGS_PER_UAR)
+
+ err = MLX5_HCA_CAP_CHECK(cmd_hca_cap, log_bf_reg_size,
+ LOG_BF_REG_SIZE_MIN,
+ LOG_BF_REG_SIZE_MAX);
+ if (err)
+ return err;
+
+#undef LOG_BF_REG_SIZE_MAX
+#undef LOG_BF_REG_SIZE_MIN
+
+ return MLX5_HCA_CAP_CHECK(cmd_hca_cap, min_dynamic_vf_msix_table_size, 0,
+ MLX5_GET(cmd_hca_cap, dst,
+ max_dynamic_vf_msix_table_size));
+}
+
+static int mlx5_adversarial_filter_general_2(struct mlx5_core_dev *dev, void *dst,
+ void *src)
+{
+ int err;
+ u32 val;
+
+ memset(dst, 0, MLX5_UN_SZ_BYTES(hca_cap_union));
+
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, dp_ordering_force);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, query_vuid);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, umr_log_entity_size_5);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_reformat_insert_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_reformat_insert_offset);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_reformat_remove_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_reformat_remove_offset);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, sf_eq_usage);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_rqt_vhca_id);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2,
+ min_mkey_log_entity_size_fixed_buffer_valid);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, log_min_mkey_entity_size);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2,
+ min_mkey_log_entity_size_fixed_buffer);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2,
+ max_mkey_log_entity_size_fixed_buffer);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_mkey_log_entity_size_mtt);
+ MLX5_HCA_CAP_ALLOW(cmd_hca_cap_2, max_num_eqs_24b);
+
+ err = MLX5_HCA_CAP_CHECK_Z(cmd_hca_cap_2, max_mkey_log_entity_size_mtt,
+ MLX5_ADAPTER_PAGE_SHIFT, 63);
+ if (err)
+ return err;
+
+ err = MLX5_HCA_CAP_CHECK_Z(cmd_hca_cap_2,
+ max_mkey_log_entity_size_fixed_buffer,
+ MLX5_ADAPTER_PAGE_SHIFT, 63);
+ if (err)
+ return err;
+
+ val = MLX5_GET(cmd_hca_cap_2, dst, max_mkey_log_entity_size_mtt) ?: 31;
+ err = MLX5_HCA_CAP_CHECK(cmd_hca_cap_2, log_min_mkey_entity_size, 0,
+ val);
+ if (err)
+ return err;
+
+ /* The fixed buffer min is don't-care when its valid bit is clear. */
+ if (!MLX5_GET(cmd_hca_cap_2, dst,
+ min_mkey_log_entity_size_fixed_buffer_valid))
+ return 0;
+
+ val = MLX5_GET(cmd_hca_cap_2, dst,
+ max_mkey_log_entity_size_fixed_buffer) ?: 31;
+ return MLX5_HCA_CAP_CHECK(cmd_hca_cap_2,
+ min_mkey_log_entity_size_fixed_buffer, 0, val);
+}
+
+static int mlx5_adversarial_filter_per_protocol(struct mlx5_core_dev *dev,
+ void *dst, void *src)
+{
+ memset(dst, 0, MLX5_UN_SZ_BYTES(hca_cap_union));
+
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps, csum_cap);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps, vlan_cap);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps,
+ self_lb_en_modifiable);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps, max_lso_cap);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps,
+ wqe_inline_mode);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps,
+ rss_ind_tbl_cap);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps,
+ cqe_checksum_full);
+ MLX5_HCA_CAP_ALLOW(per_protocol_networking_offload_caps,
+ max_vxlan_udp_ports);
+
+ return 0;
+}
+
+#undef MLX5_HCA_CAP_ALLOW
+#undef MLX5_HCA_CAP_ALLOW64
+#undef MLX5_HCA_CAP_CLAMP
+#undef MLX5_HCA_CAP_CHECK
+#undef MLX5_HCA_CAP_CHECK_Z
+
+int mlx5_store_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type,
+ void *dst, void *src)
+{
+ if (!mlx5_is_adversarial()) {
+ memcpy(dst, src, MLX5_UN_SZ_BYTES(hca_cap_union));
+ return 0;
+ }
+
+ switch (cap_type) {
+ case MLX5_CAP_GENERAL:
+ return mlx5_adversarial_filter_general(dev, dst, src);
+ case MLX5_CAP_GENERAL_2:
+ return mlx5_adversarial_filter_general_2(dev, dst, src);
+ case MLX5_CAP_ETHERNET_OFFLOADS:
+ return mlx5_adversarial_filter_per_protocol(dev, dst, src);
+
+ case MLX5_CAP_ATOMIC:
+ case MLX5_CAP_ROCE:
+ case MLX5_CAP_FLOW_TABLE:
+ case MLX5_CAP_DEV_EVENT:
+ memcpy(dst, src, MLX5_UN_SZ_BYTES(hca_cap_union));
+ break;
+
+ default:
+ memset(dst, 0, MLX5_UN_SZ_BYTES(hca_cap_union));
+ break;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index f9e10464a71b..e76a4486b5a3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -325,12 +325,12 @@ int mlx5_core_get_caps_mode(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_ty
switch (cap_mode) {
case HCA_CAP_OPMOD_GET_MAX:
- memcpy(dev->caps.hca[cap_type]->max, hca_caps,
- MLX5_UN_SZ_BYTES(hca_cap_union));
+ err = mlx5_store_caps(dev, cap_type,
+ dev->caps.hca[cap_type]->max, hca_caps);
break;
case HCA_CAP_OPMOD_GET_CUR:
- memcpy(dev->caps.hca[cap_type]->cur, hca_caps,
- MLX5_UN_SZ_BYTES(hca_cap_union));
+ err = mlx5_store_caps(dev, cap_type,
+ dev->caps.hca[cap_type]->cur, hca_caps);
break;
default:
mlx5_core_warn(dev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index d84d0424d04e..0084bed669f6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -215,6 +215,8 @@ static inline int mlx5_flexible_inlen(struct mlx5_core_dev *dev, size_t fixed,
mlx5_flexible_inlen(dev, fixed, item_size, num_items, __func__, __LINE__)
int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type);
+int mlx5_store_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type,
+ void *dst, void *src);
int mlx5_core_get_caps_mode(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type,
enum mlx5_cap_mode cap_mode);
int mlx5_query_hca_caps(struct mlx5_core_dev *dev);
--
2.18.1
next prev parent reply other threads:[~2026-11-03 16:41 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 16:39 [PATCH rdma-next 00/23] mlx5: Adversarial mode for confidential computing guests Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 01/23] net/mlx5: Add mlx5_trigger_health_work_force() Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-08 16:17 ` Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 02/23] net/mlx5: Derive adversarial mode from CC guest memory encryption Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` Yishai Hadas [this message]
2026-11-07 20:24 ` [PATCH rdma-next 03/23] net/mlx5: Add capability filtering in adversarial mode netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 04/23] net/mlx5: Add macros for reading log-based caps Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 05/23] RDMA/mlx5: Reject QP transport types not enabled by FW capability Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 06/23] RDMA/mlx5: Require IB_QPT_DRIVER for the DC vendor QP types Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 07/23] RDMA/mlx5: Derive mlx5_ib_adversarial_mode global from mlx5_core adversarial API Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 08/23] RDMA/core: Suppress kverbs_provider for adversarial_mode devices Yishai Hadas
2026-11-03 19:03 ` Jacob Moroni
2026-11-03 19:07 ` Jason Gunthorpe
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 09/23] RDMA/mlx5: Remove duplicate mlx5_ib_umr_context struct Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 10/23] RDMA/mlx5: Introduce per-CQ poll_one hook in mlx5_ib_cq Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 11/23] RDMA/mlx5: Add shadow FIFO infrastructure for UMR completions Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 12/23] RDMA/mlx5: Verify UMR CQ polling against a hostile NIC Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 13/23] RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 14/23] RDMA/mlx5: Block generic CQ poll path in adversarial mode Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 15/23] RDMA/core: Set the CQ comp_handler after its poll context is set up Yishai Hadas
2026-11-07 20:24 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 16/23] RDMA/mlx5: Ignore completion events for a CQ without a handler Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 17/23] RDMA/mlx5: Validate EQE port and GSI port before indexing devr.ports[] Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 18/23] RDMA/mlx5: Validate firmware RQ/SQ state before sqrq_trans[] lookup Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 19/23] RDMA/mlx5: Clamp log_max_cq_sz shift in CQ size checks Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 20/23] RDMA/mlx5: Clamp log_max_* shifts in QP and WQ limit checks Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 21/23] RDMA/mlx5: Clamp log_max_* shifts in query_device and ucontext paths Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 22/23] RDMA/core: Report and enforce adversarial mode via GET_CONTEXT Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 23/23] RDMA/mlx5: Advertise adversarial mode via ib_device::adversarial_mode Yishai Hadas
2026-11-07 20:25 ` netdev-bot+sashiko
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=20261103163949.1554-4-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