From 04bee524503ec06f9c38d8d4f8df16c5a7f82008 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 20 Dec 2025 04:28:55 -0500 Subject: [PATCH] Fixes for all trees Signed-off-by: Sasha Levin --- ...44-prevent-uninitialized-value-usage.patch | 45 ++ ...-integer-underflow-in-cffrml_receive.patch | 58 +++ ...erflowing-userspace-buffer-on-stats-.patch | 159 ++++++ queue-5.10/ethtool-use-phydev-variable.patch | 53 ++ ...re-packet_loopback-in-handle_mode_l2.patch | 48 ++ ...4-null-ptr-deref-in-route-error-path.patch | 80 +++ ...r-fix-use-after-free-when-updating-m.patch | 96 ++++ ..._router-fix-neighbour-use-after-free.patch | 199 ++++++++ ...l-remove-if-n_stats-checks-from-etht.patch | 68 +++ ...l-split-ethtool_get_phy_stats-into-m.patch | 168 +++++++ ...-add-vlan-id-validation-before-using.patch | 46 ++ ...he-num_tqps-in-the-vf-driver-to-appl.patch | 52 ++ ...er-add-support-for-unrecognized-stri.patch | 94 ++++ ...acer-handle-escaped-percent-properly.patch | 84 ++++ ...er-validate-format-string-parameters.patch | 195 ++++++++ ...fix-middle-attribute-validation-in-p.patch | 112 +++++ ...ways-remove-class-from-active-list-b.patch | 232 +++++++++ ...move-drr-class-from-the-active-list-.patch | 88 ++++ ...nncount-fix-leaked-ct-in-error-paths.patch | 90 ++++ ...netrom-fix-memory-leak-in-nr_sendmsg.patch | 74 +++ ...ror-code-in-pn533_acr122_poweron_rdr.patch | 37 ++ queue-5.10/series | 21 + ...44-prevent-uninitialized-value-usage.patch | 45 ++ ...-integer-underflow-in-cffrml_receive.patch | 58 +++ ...erflowing-userspace-buffer-on-stats-.patch | 159 ++++++ queue-5.15/ethtool-use-phydev-variable.patch | 53 ++ ...re-packet_loopback-in-handle_mode_l2.patch | 48 ++ ...4-null-ptr-deref-in-route-error-path.patch | 80 +++ ...r-fix-use-after-free-when-updating-m.patch | 96 ++++ ..._router-fix-neighbour-use-after-free.patch | 199 ++++++++ ...l-remove-if-n_stats-checks-from-etht.patch | 68 +++ ...l-split-ethtool_get_phy_stats-into-m.patch | 168 +++++++ ...-add-vlan-id-validation-before-using.patch | 46 ++ ...ype-of-some-variables-with-their-pri.patch | 78 +++ ...he-num_tqps-in-the-vf-driver-to-appl.patch | 52 ++ ...he-num_tqps-to-check-whether-tqp_ind.patch | 49 ++ ...er-add-support-for-unrecognized-stri.patch | 94 ++++ ...acer-handle-escaped-percent-properly.patch | 84 ++++ ...er-validate-format-string-parameters.patch | 195 ++++++++ ...fix-middle-attribute-validation-in-p.patch | 112 +++++ ...ways-remove-class-from-active-list-b.patch | 232 +++++++++ ...move-drr-class-from-the-active-list-.patch | 88 ++++ ...nncount-fix-leaked-ct-in-error-paths.patch | 90 ++++ ...netrom-fix-memory-leak-in-nr_sendmsg.patch | 74 +++ ...ror-code-in-pn533_acr122_poweron_rdr.patch | 37 ++ queue-5.15/series | 23 + ...44-prevent-uninitialized-value-usage.patch | 45 ++ ...-integer-underflow-in-cffrml_receive.patch | 58 +++ ...erflowing-userspace-buffer-on-stats-.patch | 159 ++++++ ...re-packet_loopback-in-handle_mode_l2.patch | 48 ++ ...4-null-ptr-deref-in-route-error-path.patch | 80 +++ ...r-fix-use-after-free-when-updating-m.patch | 96 ++++ ..._router-fix-neighbour-use-after-free.patch | 199 ++++++++ ...l-remove-if-n_stats-checks-from-etht.patch | 68 +++ ...l-split-ethtool_get_phy_stats-into-m.patch | 168 +++++++ ...-add-vlan-id-validation-before-using.patch | 46 ++ ...he-num_tqps-in-the-vf-driver-to-appl.patch | 52 ++ ...he-num_tqps-to-check-whether-tqp_ind.patch | 49 ++ ...et-mlx5-create-a-new-profile-for-sfs.patch | 139 ++++++ ...-firmware-reset-in-shutdown-callback.patch | 38 ++ ...t-clear-reset-requested-on-drain_fw_.patch | 45 ++ ...er-add-support-for-unrecognized-stri.patch | 94 ++++ ...acer-handle-escaped-percent-properly.patch | 84 ++++ ...er-validate-format-string-parameters.patch | 195 ++++++++ ...fix-middle-attribute-validation-in-p.patch | 112 +++++ ...ways-remove-class-from-active-list-b.patch | 232 +++++++++ ...move-drr-class-from-the-active-list-.patch | 88 ++++ ...nncount-fix-leaked-ct-in-error-paths.patch | 90 ++++ ...netrom-fix-memory-leak-in-nr_sendmsg.patch | 74 +++ ...ror-code-in-pn533_acr122_poweron_rdr.patch | 37 ++ queue-6.1/series | 24 + queue-6.12/bnxt_en-fix-xdp_tx-path.patch | 74 +++ ...44-prevent-uninitialized-value-usage.patch | 45 ++ ...-integer-underflow-in-cffrml_receive.patch | 58 +++ ...erflowing-userspace-buffer-on-stats-.patch | 159 ++++++ ...-add-coverage-for-reporting-max_pasi.patch | 153 ++++++ ...-check-for-overflow-in-iommu_test_op.patch | 57 +++ ...-make-it-clearer-to-gcc-that-the-acc.patch | 71 +++ ...-update-hw_info-coverage-for-an-inpu.patch | 178 +++++++ ...re-packet_loopback-in-handle_mode_l2.patch | 48 ++ ...4-null-ptr-deref-in-route-error-path.patch | 80 +++ ...r-fix-use-after-free-when-updating-m.patch | 96 ++++ ..._router-fix-neighbour-use-after-free.patch | 199 ++++++++ ...outer-fix-possible-neighbour-referen.patch | 64 +++ ...-transmit-redirected-xdp-frames-when.patch | 66 +++ ...err007885-workaround-for-xdp-tx-path.patch | 49 ++ ...plicate-handshake-cancellations-leak.patch | 61 +++ ...-add-vlan-id-validation-before-using.patch | 46 ++ ...he-num_tqps-in-the-vf-driver-to-appl.patch | 52 ++ ...he-num_tqps-to-check-whether-tqp_ind.patch | 49 ++ ...-firmware-reset-in-shutdown-callback.patch | 38 ++ ...t-clear-reset-requested-on-drain_fw_.patch | 45 ++ ...acer-handle-escaped-percent-properly.patch | 84 ++++ ...er-validate-format-string-parameters.patch | 195 ++++++++ ...erialize-firmware-reset-with-devlink.patch | 209 ++++++++ ...fix-middle-attribute-validation-in-p.patch | 112 +++++ ...ways-remove-class-from-active-list-b.patch | 232 +++++++++ ...move-drr-class-from-the-active-list-.patch | 88 ++++ ...nncount-fix-leaked-ct-in-error-paths.patch | 90 ++++ ...-nf_nat-remove-bogus-direction-check.patch | 129 +++++ ...les-remove-redundant-chain-validatio.patch | 59 +++ ...netrom-fix-memory-leak-in-nr_sendmsg.patch | 74 +++ ...ror-code-in-pn533_acr122_poweron_rdr.patch | 37 ++ ...ter-packetdrill-avoid-failure-on-hz-.patch | 41 ++ queue-6.12/series | 33 ++ queue-6.18/bnxt_en-fix-xdp_tx-path.patch | 74 +++ ...44-prevent-uninitialized-value-usage.patch | 45 ++ ...-integer-underflow-in-cffrml_receive.patch | 58 +++ ...1939_sk_bind-fail-if-device-is-no-lo.patch | 54 ++ ...erflowing-userspace-buffer-on-stats-.patch | 159 ++++++ ...inet-frags-add-inet_frag_queue_flush.patch | 96 ++++ ...d-theoretical-race-in-ip_frag_reinit.patch | 67 +++ ...flush-pending-skbs-in-fqdir_pre_exit.patch | 186 +++++++ ...-check-for-overflow-in-iommu_test_op.patch | 57 +++ ...-make-it-clearer-to-gcc-that-the-acc.patch | 71 +++ ...re-packet_loopback-in-handle_mode_l2.patch | 48 ++ ...4-null-ptr-deref-in-route-error-path.patch | 80 +++ ...r-fix-use-after-free-when-updating-m.patch | 96 ++++ ..._router-fix-neighbour-use-after-free.patch | 199 ++++++++ ...outer-fix-possible-neighbour-referen.patch | 64 +++ ...-transmit-redirected-xdp-frames-when.patch | 66 +++ ...err007885-workaround-for-xdp-tx-path.patch | 49 ++ ...plicate-handshake-cancellations-leak.patch | 61 +++ ...-add-vlan-id-validation-before-using.patch | 46 ++ ...he-num_tqps-in-the-vf-driver-to-appl.patch | 52 ++ ...he-num_tqps-to-check-whether-tqp_ind.patch | 49 ++ ...-firmware-reset-in-shutdown-callback.patch | 38 ++ ...ble-unregister-of-hca_ports-componen.patch | 82 +++ ...t-clear-reset-requested-on-drain_fw_.patch | 45 ++ ...acer-handle-escaped-percent-properly.patch | 84 ++++ ...er-validate-format-string-parameters.patch | 195 ++++++++ ...et-mlx5-make-enable_mpesw-idempotent.patch | 58 +++ ...erialize-firmware-reset-with-devlink.patch | 209 ++++++++ ...-mlx5e-avoid-unregistering-psp-twice.patch | 58 +++ ...include-psp-in-the-hard-mtu-calculat.patch | 53 ++ ...r-neighbor-resolution-for-unresolved.patch | 60 +++ ...6_dst_lookup-instead-of-ipv6_dst_loo.patch | 50 ++ ...fix-middle-attribute-validation-in-p.patch | 112 +++++ ...allow-clkout-to-be-disabled-on-rtl82.patch | 112 +++++ ...create-rtl8211f_config_phy_eee-helpe.patch | 69 +++ ...ealtek-eliminate-has_phycr2-variable.patch | 66 +++ ...altek-eliminate-priv-phycr1-variable.patch | 118 +++++ ...altek-eliminate-priv-phycr2-variable.patch | 112 +++++ ...vd-restore-disabling-of-phy-mode-eee.patch | 71 +++ ...ways-remove-class-from-active-list-b.patch | 232 +++++++++ ...move-drr-class-from-the-active-list-.patch | 88 ++++ ...eth-add-ptp_1588_clock_optional-depe.patch | 55 ++ ...nncount-fix-leaked-ct-in-error-paths.patch | 90 ++++ ...-nf_nat-remove-bogus-direction-check.patch | 129 +++++ ...les-remove-redundant-chain-validatio.patch | 59 +++ ...netrom-fix-memory-leak-in-nr_sendmsg.patch | 74 +++ ...ror-code-in-pn533_acr122_poweron_rdr.patch | 37 ++ ...-support-compilers-without-flex-arra.patch | 47 ++ .../selftests-net-fix-build-warnings.patch | 60 +++ .../selftests-net-tfo-fix-build-warning.patch | 47 ++ ...ter-packetdrill-avoid-failure-on-hz-.patch | 41 ++ ...ter-prefer-xfail-in-case-race-wasn-t.patch | 65 +++ queue-6.18/series | 52 ++ ...44-prevent-uninitialized-value-usage.patch | 45 ++ ...-integer-underflow-in-cffrml_receive.patch | 58 +++ ...erflowing-userspace-buffer-on-stats-.patch | 159 ++++++ ...-check-for-overflow-in-iommu_test_op.patch | 57 +++ ...re-packet_loopback-in-handle_mode_l2.patch | 48 ++ ...4-null-ptr-deref-in-route-error-path.patch | 80 +++ ...r-fix-use-after-free-when-updating-m.patch | 96 ++++ ..._router-fix-neighbour-use-after-free.patch | 199 ++++++++ ...outer-fix-possible-neighbour-referen.patch | 64 +++ ...-transmit-redirected-xdp-frames-when.patch | 66 +++ ...err007885-workaround-for-xdp-tx-path.patch | 49 ++ ...plicate-handshake-cancellations-leak.patch | 61 +++ ...-add-vlan-id-validation-before-using.patch | 46 ++ ...he-num_tqps-in-the-vf-driver-to-appl.patch | 52 ++ ...he-num_tqps-to-check-whether-tqp_ind.patch | 49 ++ ...-firmware-reset-in-shutdown-callback.patch | 38 ++ ...t-clear-reset-requested-on-drain_fw_.patch | 45 ++ ...acer-handle-escaped-percent-properly.patch | 84 ++++ ...er-validate-format-string-parameters.patch | 195 ++++++++ ...erialize-firmware-reset-with-devlink.patch | 209 ++++++++ ...tplug-check-on-sync-reset-using-hot-.patch | 66 +++ ...fix-middle-attribute-validation-in-p.patch | 112 +++++ ...ways-remove-class-from-active-list-b.patch | 232 +++++++++ ...move-drr-class-from-the-active-list-.patch | 88 ++++ ...nncount-fix-leaked-ct-in-error-paths.patch | 90 ++++ ...les-allow-loads-only-when-register-i.patch | 152 ++++++ ...les-pass-context-structure-to-nft_pa.patch | 470 ++++++++++++++++++ ...les-remove-redundant-chain-validatio.patch | 59 +++ ...netrom-fix-memory-leak-in-nr_sendmsg.patch | 74 +++ ...ror-code-in-pn533_acr122_poweron_rdr.patch | 37 ++ queue-6.6/series | 30 ++ 189 files changed, 17173 insertions(+) create mode 100644 queue-5.10/broadcom-b44-prevent-uninitialized-value-usage.patch create mode 100644 queue-5.10/caif-fix-integer-underflow-in-cffrml_receive.patch create mode 100644 queue-5.10/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch create mode 100644 queue-5.10/ethtool-use-phydev-variable.patch create mode 100644 queue-5.10/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch create mode 100644 queue-5.10/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch create mode 100644 queue-5.10/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch create mode 100644 queue-5.10/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch create mode 100644 queue-5.10/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch create mode 100644 queue-5.10/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch create mode 100644 queue-5.10/net-hns3-add-vlan-id-validation-before-using.patch create mode 100644 queue-5.10/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch create mode 100644 queue-5.10/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch create mode 100644 queue-5.10/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch create mode 100644 queue-5.10/net-mlx5-fw_tracer-validate-format-string-parameters.patch create mode 100644 queue-5.10/net-openvswitch-fix-middle-attribute-validation-in-p.patch create mode 100644 queue-5.10/net-sched-ets-always-remove-class-from-active-list-b.patch create mode 100644 queue-5.10/net-sched-ets-remove-drr-class-from-the-active-list-.patch create mode 100644 queue-5.10/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch create mode 100644 queue-5.10/netrom-fix-memory-leak-in-nr_sendmsg.patch create mode 100644 queue-5.10/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch create mode 100644 queue-5.15/broadcom-b44-prevent-uninitialized-value-usage.patch create mode 100644 queue-5.15/caif-fix-integer-underflow-in-cffrml_receive.patch create mode 100644 queue-5.15/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch create mode 100644 queue-5.15/ethtool-use-phydev-variable.patch create mode 100644 queue-5.15/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch create mode 100644 queue-5.15/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch create mode 100644 queue-5.15/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch create mode 100644 queue-5.15/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch create mode 100644 queue-5.15/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch create mode 100644 queue-5.15/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch create mode 100644 queue-5.15/net-hns3-add-vlan-id-validation-before-using.patch create mode 100644 queue-5.15/net-hns3-align-type-of-some-variables-with-their-pri.patch create mode 100644 queue-5.15/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch create mode 100644 queue-5.15/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch create mode 100644 queue-5.15/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch create mode 100644 queue-5.15/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch create mode 100644 queue-5.15/net-mlx5-fw_tracer-validate-format-string-parameters.patch create mode 100644 queue-5.15/net-openvswitch-fix-middle-attribute-validation-in-p.patch create mode 100644 queue-5.15/net-sched-ets-always-remove-class-from-active-list-b.patch create mode 100644 queue-5.15/net-sched-ets-remove-drr-class-from-the-active-list-.patch create mode 100644 queue-5.15/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch create mode 100644 queue-5.15/netrom-fix-memory-leak-in-nr_sendmsg.patch create mode 100644 queue-5.15/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch create mode 100644 queue-6.1/broadcom-b44-prevent-uninitialized-value-usage.patch create mode 100644 queue-6.1/caif-fix-integer-underflow-in-cffrml_receive.patch create mode 100644 queue-6.1/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch create mode 100644 queue-6.1/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch create mode 100644 queue-6.1/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch create mode 100644 queue-6.1/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch create mode 100644 queue-6.1/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch create mode 100644 queue-6.1/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch create mode 100644 queue-6.1/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch create mode 100644 queue-6.1/net-hns3-add-vlan-id-validation-before-using.patch create mode 100644 queue-6.1/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch create mode 100644 queue-6.1/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch create mode 100644 queue-6.1/net-mlx5-create-a-new-profile-for-sfs.patch create mode 100644 queue-6.1/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch create mode 100644 queue-6.1/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch create mode 100644 queue-6.1/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch create mode 100644 queue-6.1/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch create mode 100644 queue-6.1/net-mlx5-fw_tracer-validate-format-string-parameters.patch create mode 100644 queue-6.1/net-openvswitch-fix-middle-attribute-validation-in-p.patch create mode 100644 queue-6.1/net-sched-ets-always-remove-class-from-active-list-b.patch create mode 100644 queue-6.1/net-sched-ets-remove-drr-class-from-the-active-list-.patch create mode 100644 queue-6.1/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch create mode 100644 queue-6.1/netrom-fix-memory-leak-in-nr_sendmsg.patch create mode 100644 queue-6.1/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch create mode 100644 queue-6.12/bnxt_en-fix-xdp_tx-path.patch create mode 100644 queue-6.12/broadcom-b44-prevent-uninitialized-value-usage.patch create mode 100644 queue-6.12/caif-fix-integer-underflow-in-cffrml_receive.patch create mode 100644 queue-6.12/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch create mode 100644 queue-6.12/iommufd-selftest-add-coverage-for-reporting-max_pasi.patch create mode 100644 queue-6.12/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch create mode 100644 queue-6.12/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch create mode 100644 queue-6.12/iommufd-selftest-update-hw_info-coverage-for-an-inpu.patch create mode 100644 queue-6.12/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch create mode 100644 queue-6.12/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch create mode 100644 queue-6.12/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch create mode 100644 queue-6.12/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch create mode 100644 queue-6.12/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch create mode 100644 queue-6.12/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch create mode 100644 queue-6.12/net-fec-err007885-workaround-for-xdp-tx-path.patch create mode 100644 queue-6.12/net-handshake-duplicate-handshake-cancellations-leak.patch create mode 100644 queue-6.12/net-hns3-add-vlan-id-validation-before-using.patch create mode 100644 queue-6.12/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch create mode 100644 queue-6.12/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch create mode 100644 queue-6.12/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch create mode 100644 queue-6.12/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch create mode 100644 queue-6.12/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch create mode 100644 queue-6.12/net-mlx5-fw_tracer-validate-format-string-parameters.patch create mode 100644 queue-6.12/net-mlx5-serialize-firmware-reset-with-devlink.patch create mode 100644 queue-6.12/net-openvswitch-fix-middle-attribute-validation-in-p.patch create mode 100644 queue-6.12/net-sched-ets-always-remove-class-from-active-list-b.patch create mode 100644 queue-6.12/net-sched-ets-remove-drr-class-from-the-active-list-.patch create mode 100644 queue-6.12/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch create mode 100644 queue-6.12/netfilter-nf_nat-remove-bogus-direction-check.patch create mode 100644 queue-6.12/netfilter-nf_tables-remove-redundant-chain-validatio.patch create mode 100644 queue-6.12/netrom-fix-memory-leak-in-nr_sendmsg.patch create mode 100644 queue-6.12/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch create mode 100644 queue-6.12/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch create mode 100644 queue-6.18/bnxt_en-fix-xdp_tx-path.patch create mode 100644 queue-6.18/broadcom-b44-prevent-uninitialized-value-usage.patch create mode 100644 queue-6.18/caif-fix-integer-underflow-in-cffrml_receive.patch create mode 100644 queue-6.18/can-j1939-make-j1939_sk_bind-fail-if-device-is-no-lo.patch create mode 100644 queue-6.18/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch create mode 100644 queue-6.18/inet-frags-add-inet_frag_queue_flush.patch create mode 100644 queue-6.18/inet-frags-avoid-theoretical-race-in-ip_frag_reinit.patch create mode 100644 queue-6.18/inet-frags-flush-pending-skbs-in-fqdir_pre_exit.patch create mode 100644 queue-6.18/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch create mode 100644 queue-6.18/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch create mode 100644 queue-6.18/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch create mode 100644 queue-6.18/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch create mode 100644 queue-6.18/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch create mode 100644 queue-6.18/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch create mode 100644 queue-6.18/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch create mode 100644 queue-6.18/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch create mode 100644 queue-6.18/net-fec-err007885-workaround-for-xdp-tx-path.patch create mode 100644 queue-6.18/net-handshake-duplicate-handshake-cancellations-leak.patch create mode 100644 queue-6.18/net-hns3-add-vlan-id-validation-before-using.patch create mode 100644 queue-6.18/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch create mode 100644 queue-6.18/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch create mode 100644 queue-6.18/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch create mode 100644 queue-6.18/net-mlx5-fix-double-unregister-of-hca_ports-componen.patch create mode 100644 queue-6.18/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch create mode 100644 queue-6.18/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch create mode 100644 queue-6.18/net-mlx5-fw_tracer-validate-format-string-parameters.patch create mode 100644 queue-6.18/net-mlx5-make-enable_mpesw-idempotent.patch create mode 100644 queue-6.18/net-mlx5-serialize-firmware-reset-with-devlink.patch create mode 100644 queue-6.18/net-mlx5e-avoid-unregistering-psp-twice.patch create mode 100644 queue-6.18/net-mlx5e-don-t-include-psp-in-the-hard-mtu-calculat.patch create mode 100644 queue-6.18/net-mlx5e-trigger-neighbor-resolution-for-unresolved.patch create mode 100644 queue-6.18/net-mlx5e-use-ip6_dst_lookup-instead-of-ipv6_dst_loo.patch create mode 100644 queue-6.18/net-openvswitch-fix-middle-attribute-validation-in-p.patch create mode 100644 queue-6.18/net-phy-realtek-allow-clkout-to-be-disabled-on-rtl82.patch create mode 100644 queue-6.18/net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch create mode 100644 queue-6.18/net-phy-realtek-eliminate-has_phycr2-variable.patch create mode 100644 queue-6.18/net-phy-realtek-eliminate-priv-phycr1-variable.patch create mode 100644 queue-6.18/net-phy-realtek-eliminate-priv-phycr2-variable.patch create mode 100644 queue-6.18/net-phy-rtl8211fvd-restore-disabling-of-phy-mode-eee.patch create mode 100644 queue-6.18/net-sched-ets-always-remove-class-from-active-list-b.patch create mode 100644 queue-6.18/net-sched-ets-remove-drr-class-from-the-active-list-.patch create mode 100644 queue-6.18/net-ti-icssg-prueth-add-ptp_1588_clock_optional-depe.patch create mode 100644 queue-6.18/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch create mode 100644 queue-6.18/netfilter-nf_nat-remove-bogus-direction-check.patch create mode 100644 queue-6.18/netfilter-nf_tables-remove-redundant-chain-validatio.patch create mode 100644 queue-6.18/netrom-fix-memory-leak-in-nr_sendmsg.patch create mode 100644 queue-6.18/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch create mode 100644 queue-6.18/selftest-af_unix-support-compilers-without-flex-arra.patch create mode 100644 queue-6.18/selftests-net-fix-build-warnings.patch create mode 100644 queue-6.18/selftests-net-tfo-fix-build-warning.patch create mode 100644 queue-6.18/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch create mode 100644 queue-6.18/selftests-netfilter-prefer-xfail-in-case-race-wasn-t.patch create mode 100644 queue-6.6/broadcom-b44-prevent-uninitialized-value-usage.patch create mode 100644 queue-6.6/caif-fix-integer-underflow-in-cffrml_receive.patch create mode 100644 queue-6.6/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch create mode 100644 queue-6.6/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch create mode 100644 queue-6.6/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch create mode 100644 queue-6.6/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch create mode 100644 queue-6.6/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch create mode 100644 queue-6.6/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch create mode 100644 queue-6.6/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch create mode 100644 queue-6.6/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch create mode 100644 queue-6.6/net-fec-err007885-workaround-for-xdp-tx-path.patch create mode 100644 queue-6.6/net-handshake-duplicate-handshake-cancellations-leak.patch create mode 100644 queue-6.6/net-hns3-add-vlan-id-validation-before-using.patch create mode 100644 queue-6.6/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch create mode 100644 queue-6.6/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch create mode 100644 queue-6.6/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch create mode 100644 queue-6.6/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch create mode 100644 queue-6.6/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch create mode 100644 queue-6.6/net-mlx5-fw_tracer-validate-format-string-parameters.patch create mode 100644 queue-6.6/net-mlx5-serialize-firmware-reset-with-devlink.patch create mode 100644 queue-6.6/net-mlx5-skip-hotplug-check-on-sync-reset-using-hot-.patch create mode 100644 queue-6.6/net-openvswitch-fix-middle-attribute-validation-in-p.patch create mode 100644 queue-6.6/net-sched-ets-always-remove-class-from-active-list-b.patch create mode 100644 queue-6.6/net-sched-ets-remove-drr-class-from-the-active-list-.patch create mode 100644 queue-6.6/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch create mode 100644 queue-6.6/netfilter-nf_tables-allow-loads-only-when-register-i.patch create mode 100644 queue-6.6/netfilter-nf_tables-pass-context-structure-to-nft_pa.patch create mode 100644 queue-6.6/netfilter-nf_tables-remove-redundant-chain-validatio.patch create mode 100644 queue-6.6/netrom-fix-memory-leak-in-nr_sendmsg.patch create mode 100644 queue-6.6/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch diff --git a/queue-5.10/broadcom-b44-prevent-uninitialized-value-usage.patch b/queue-5.10/broadcom-b44-prevent-uninitialized-value-usage.patch new file mode 100644 index 0000000000..490b30b275 --- /dev/null +++ b/queue-5.10/broadcom-b44-prevent-uninitialized-value-usage.patch @@ -0,0 +1,45 @@ +From d434e3a21ca076ef40aa7565d08b730394a33d17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 18:58:16 +0300 +Subject: broadcom: b44: prevent uninitialized value usage + +From: Alexey Simakov + +[ Upstream commit 50b3db3e11864cb4e18ff099cfb38e11e7f87a68 ] + +On execution path with raised B44_FLAG_EXTERNAL_PHY, b44_readphy() +leaves bmcr value uninitialized and it is used later in the code. + +Add check of this flag at the beginning of the b44_nway_reset() and +exit early of the function with restarting autonegotiation if an +external PHY is used. + +Fixes: 753f492093da ("[B44]: port to native ssb support") +Reviewed-by: Jonas Gorski +Reviewed-by: Andrew Lunn +Signed-off-by: Alexey Simakov +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20251205155815.4348-1-bigalex934@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/b44.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c +index 7ad9a47156912..f29a38675afb6 100644 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -1809,6 +1809,9 @@ static int b44_nway_reset(struct net_device *dev) + u32 bmcr; + int r; + ++ if (bp->flags & B44_FLAG_EXTERNAL_PHY) ++ return phy_ethtool_nway_reset(dev); ++ + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); +-- +2.51.0 + diff --git a/queue-5.10/caif-fix-integer-underflow-in-cffrml_receive.patch b/queue-5.10/caif-fix-integer-underflow-in-cffrml_receive.patch new file mode 100644 index 0000000000..e0f6a019fa --- /dev/null +++ b/queue-5.10/caif-fix-integer-underflow-in-cffrml_receive.patch @@ -0,0 +1,58 @@ +From 68d9a2f745456c6ac7633177d84076632efe8a1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 21:30:47 +0800 +Subject: caif: fix integer underflow in cffrml_receive() + +From: Junrui Luo + +[ Upstream commit 8a11ff0948b5ad09b71896b7ccc850625f9878d1 ] + +The cffrml_receive() function extracts a length field from the packet +header and, when FCS is disabled, subtracts 2 from this length without +validating that len >= 2. + +If an attacker sends a malicious packet with a length field of 0 or 1 +to an interface with FCS disabled, the subtraction causes an integer +underflow. + +This can lead to memory exhaustion and kernel instability, potential +information disclosure if padding contains uninitialized kernel memory. + +Fix this by validating that len >= 2 before performing the subtraction. + +Reported-by: Yuhao Jiang +Reported-by: Junrui Luo +Fixes: b482cd2053e3 ("net-caif: add CAIF core protocol stack") +Signed-off-by: Junrui Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/SYBPR01MB7881511122BAFEA8212A1608AFA6A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/caif/cffrml.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c +index 6651a8dc62e04..d4d63586053ad 100644 +--- a/net/caif/cffrml.c ++++ b/net/caif/cffrml.c +@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) + len = le16_to_cpu(tmp); + + /* Subtract for FCS on length if FCS is not used. */ +- if (!this->dofcs) ++ if (!this->dofcs) { ++ if (len < 2) { ++ ++cffrml_rcv_error; ++ pr_err("Invalid frame length (%d)\n", len); ++ cfpkt_destroy(pkt); ++ return -EPROTO; ++ } + len -= 2; ++ } + + if (cfpkt_setlen(pkt, len) < 0) { + ++cffrml_rcv_error; +-- +2.51.0 + diff --git a/queue-5.10/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch b/queue-5.10/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch new file mode 100644 index 0000000000..a197f4a684 --- /dev/null +++ b/queue-5.10/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch @@ -0,0 +1,159 @@ +From 803f1dcc56542dbc4b2b117f9f7a746626727a91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 14:19:01 +0200 +Subject: ethtool: Avoid overflowing userspace buffer on stats query + +From: Gal Pressman + +[ Upstream commit 7b07be1ff1cb6c49869910518650e8d0abc7d25f ] + +The ethtool -S command operates across three ioctl calls: +ETHTOOL_GSSET_INFO for the size, ETHTOOL_GSTRINGS for the names, and +ETHTOOL_GSTATS for the values. + +If the number of stats changes between these calls (e.g., due to device +reconfiguration), userspace's buffer allocation will be incorrect, +potentially leading to buffer overflow. + +Drivers are generally expected to maintain stable stat counts, but some +drivers (e.g., mlx5, bnx2x, bna, ksz884x) use dynamic counters, making +this scenario possible. + +Some drivers try to handle this internally: +- bnad_get_ethtool_stats() returns early in case stats.n_stats is not + equal to the driver's stats count. +- micrel/ksz884x also makes sure not to write anything beyond + stats.n_stats and overflow the buffer. + +However, both use stats.n_stats which is already assigned with the value +returned from get_sset_count(), hence won't solve the issue described +here. + +Change ethtool_get_strings(), ethtool_get_stats(), +ethtool_get_phy_stats() to not return anything in case of a mismatch +between userspace's size and get_sset_size(), to prevent buffer +overflow. +The returned n_stats value will be equal to zero, to reflect that +nothing has been returned. + +This could result in one of two cases when using upstream ethtool, +depending on when the size change is detected: +1. When detected in ethtool_get_strings(): + # ethtool -S eth2 + no stats available + +2. When detected in get stats, all stats will be reported as zero. + +Both cases are presumably transient, and a subsequent ethtool call +should succeed. + +Other than the overflow avoidance, these two cases are very evident (no +output/cleared stats), which is arguably better than presenting +incorrect/shifted stats. +I also considered returning an error instead of a "silent" response, but +that seems more destructive towards userspace apps. + +Notes: +- This patch does not claim to fix the inherent race, it only makes sure + that we do not overflow the userspace buffer, and makes for a more + predictable behavior. + +- RTNL lock is held during each ioctl, the race window exists between + the separate ioctl calls when the lock is released. + +- Userspace ethtool always fills stats.n_stats, but it is likely that + these stats ioctls are implemented in other userspace applications + which might not fill it. The added code checks that it's not zero, + to prevent any regressions. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Dragos Tatulea +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Link: https://patch.msgid.link/20251208121901.3203692-1-gal@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 2ac9cf1c36ba6..7fef4bbfb210a 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1909,7 +1909,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + return -ENOMEM; + WARN_ON_ONCE(!ret); + +- gstrings.len = ret; ++ if (gstrings.len && gstrings.len != ret) ++ gstrings.len = 0; ++ else ++ gstrings.len = ret; + + if (gstrings.len) { + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); +@@ -2010,10 +2013,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (stats.n_stats && stats.n_stats != n_stats) ++ stats.n_stats = 0; ++ else ++ stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (stats.n_stats) { ++ data = vzalloc(array_size(stats.n_stats, sizeof(u64))); + if (!data) + return -ENOMEM; + ops->get_ethtool_stats(dev, &stats, data); +@@ -2025,7 +2031,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + goto out; + ret = 0; + +@@ -2061,6 +2069,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, + return -EOPNOTSUPP; + + n_stats = phy_ops->get_sset_count(phydev); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2081,6 +2093,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev, + return -EOPNOTSUPP; + + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2117,7 +2133,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + } + + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + ret = -EFAULT; + + out: +-- +2.51.0 + diff --git a/queue-5.10/ethtool-use-phydev-variable.patch b/queue-5.10/ethtool-use-phydev-variable.patch new file mode 100644 index 0000000000..4eba0da8bb --- /dev/null +++ b/queue-5.10/ethtool-use-phydev-variable.patch @@ -0,0 +1,53 @@ +From 616c08618d581c1c9b0a47d9cd08e2d365e3912d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jan 2022 06:10:20 -0800 +Subject: ethtool: use phydev variable + +From: Tom Rix + +[ Upstream commit ccd21ec5b8dd9b8a528a70315cee95fc1dd79d20 ] + +In ethtool_get_phy_stats(), the phydev varaible is set to +dev->phydev but dev->phydev is still used. Replace +dev->phydev uses with phydev. + +Signed-off-by: Tom Rix +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 0a588545d3526..ede11854f493f 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2046,9 +2046,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) + return -EOPNOTSUPP; + +- if (dev->phydev && !ops->get_ethtool_phy_stats && ++ if (phydev && !ops->get_ethtool_phy_stats && + phy_ops && phy_ops->get_sset_count) +- n_stats = phy_ops->get_sset_count(dev->phydev); ++ n_stats = phy_ops->get_sset_count(phydev); + else + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); + if (n_stats < 0) +@@ -2068,9 +2068,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (!data) + return -ENOMEM; + +- if (dev->phydev && !ops->get_ethtool_phy_stats && ++ if (phydev && !ops->get_ethtool_phy_stats && + phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(dev->phydev, &stats, data); ++ ret = phy_ops->get_stats(phydev, &stats, data); + if (ret < 0) + goto out; + } else { +-- +2.51.0 + diff --git a/queue-5.10/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch b/queue-5.10/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch new file mode 100644 index 0000000000..86139c7029 --- /dev/null +++ b/queue-5.10/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch @@ -0,0 +1,48 @@ +From db048afb39a142078013fba9fd9944a58c8c0590 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 13:39:03 +0300 +Subject: ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() + +From: Dmitry Skorodumov + +[ Upstream commit 0c57ff008a11f24f7f05fa760222692a00465fec ] + +Packets with pkt_type == PACKET_LOOPBACK are captured by +handle_frame() function, but they don't have L2 header. +We should not process them in handle_mode_l2(). + +This doesn't affect old L2 functionality, since handling +was anyway incorrect. + +Handle them the same way as in br_handle_frame(): +just pass the skb. + +To observe invalid behaviour, just start "ping -b" on bcast address +of port-interface. + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Signed-off-by: Dmitry Skorodumov +Link: https://patch.msgid.link/20251202103906.4087675-1-skorodumov.dmitry@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index d04b1450875b6..a113a06c98a55 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -726,6 +726,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + ++ if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) ++ return RX_HANDLER_PASS; ++ + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-5.10/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch b/queue-5.10/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch new file mode 100644 index 0000000000..5de033cd7f --- /dev/null +++ b/queue-5.10/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch @@ -0,0 +1,80 @@ +From 95c52589715514f3456f72973857d1bf4dacae4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 16:52:13 +0800 +Subject: ipvs: fix ipv4 null-ptr-deref in route error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Slavin Liu + +[ Upstream commit ad891bb3d079a46a821bf2b8867854645191bab0 ] + +The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure() +without ensuring skb->dev is set, leading to a NULL pointer dereference +in fib_compute_spec_dst() when ipv4_link_failure() attempts to send +ICMP destination unreachable messages. + +The issue emerged after commit ed0de45a1008 ("ipv4: recompile ip options +in ipv4_link_failure") started calling __ip_options_compile() from +ipv4_link_failure(). This code path eventually calls fib_compute_spec_dst() +which dereferences skb->dev. An attempt was made to fix the NULL skb->dev +dereference in commit 0113d9c9d1cc ("ipv4: fix null-deref in +ipv4_link_failure"), but it only addressed the immediate dev_net(skb->dev) +dereference by using a fallback device. The fix was incomplete because +fib_compute_spec_dst() later in the call chain still accesses skb->dev +directly, which remains NULL when IPVS calls dst_link_failure(). + +The crash occurs when: +1. IPVS processes a packet in NAT mode with a misconfigured destination +2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route +3. The error path calls dst_link_failure(skb) with skb->dev == NULL +4. ipv4_link_failure() → ipv4_send_dest_unreach() → + __ip_options_compile() → fib_compute_spec_dst() +5. fib_compute_spec_dst() dereferences NULL skb->dev + +Apply the same fix used for IPv6 in commit 326bf17ea5d4 ("ipvs: fix +ipv6 route unreach panic"): set skb->dev from skb_dst(skb)->dev before +calling dst_link_failure(). + +KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f] +CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2 +RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233 +RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285 +Call Trace: + + spec_dst_fill net/ipv4/ip_options.c:232 + spec_dst_fill net/ipv4/ip_options.c:229 + __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330 + ipv4_send_dest_unreach net/ipv4/route.c:1252 + ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265 + dst_link_failure include/net/dst.h:437 + __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412 + ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764 + +Fixes: ed0de45a1008 ("ipv4: recompile ip options in ipv4_link_failure") +Signed-off-by: Slavin Liu +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/ipvs/ip_vs_xmit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index c87dbc8970023..f82834349ca2c 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -420,6 +420,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + return -1; + + err_unreach: ++ if (!skb->dev) ++ skb->dev = skb_dst(skb)->dev; ++ + dst_link_failure(skb); + return -1; + } +-- +2.51.0 + diff --git a/queue-5.10/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch b/queue-5.10/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch new file mode 100644 index 0000000000..83cbb750c4 --- /dev/null +++ b/queue-5.10/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch @@ -0,0 +1,96 @@ +From e5ba72f92b3372b7a7f6c4ed51b9f7ea8b757b66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:13 +0100 +Subject: mlxsw: spectrum_mr: Fix use-after-free when updating multicast route + stats + +From: Ido Schimmel + +[ Upstream commit 8ac1dacec458f55f871f7153242ed6ab60373b90 ] + +Cited commit added a dedicated mutex (instead of RTNL) to protect the +multicast route list, so that it will not change while the driver +periodically traverses it in order to update the kernel about multicast +route stats that were queried from the device. + +One instance of list entry deletion (during route replace) was missed +and it can result in a use-after-free [1]. + +Fix by acquiring the mutex before deleting the entry from the list and +releasing it afterwards. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] +Read of size 8 at addr ffff8881523c2fa8 by task kworker/2:5/22043 + +CPU: 2 UID: 0 PID: 22043 Comm: kworker/2:5 Not tainted 6.18.0-rc1-custom-g1a3d6d7cd014 #1 PREEMPT(full) +Hardware name: Mellanox Technologies Ltd. MSN2010/SA002610, BIOS 5.6.5 08/24/2017 +Workqueue: mlxsw_core mlxsw_sp_mr_stats_update [mlxsw_spectrum] +Call Trace: + + dump_stack_lvl+0xba/0x110 + print_report+0x174/0x4f5 + kasan_report+0xdf/0x110 + mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + mlxsw_sp_mr_route_add+0xd8/0x4770 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x43/0x70 + kfree+0x14e/0x700 + mlxsw_sp_mr_route_add+0x2dea/0x4770 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:444 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Fixes: f38656d06725 ("mlxsw: spectrum_mr: Protect multicast route list with a lock") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/f996feecfd59fde297964bfc85040b6d83ec6089.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +index ee308d9aedcdc..d8a4bbb8e8998 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table, + rhashtable_remove_fast(&mr_table->route_ht, + &mr_orig_route->ht_node, + mlxsw_sp_mr_route_ht_params); ++ mutex_lock(&mr_table->route_list_lock); + list_del(&mr_orig_route->node); ++ mutex_unlock(&mr_table->route_list_lock); + mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); + } + +-- +2.51.0 + diff --git a/queue-5.10/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch b/queue-5.10/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch new file mode 100644 index 0000000000..726007b5f8 --- /dev/null +++ b/queue-5.10/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch @@ -0,0 +1,199 @@ +From eb4469628915ccd9c723b7df03ddd2ecd7eee30d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:12 +0100 +Subject: mlxsw: spectrum_router: Fix neighbour use-after-free + +From: Ido Schimmel + +[ Upstream commit 8b0e69763ef948fb872a7767df4be665d18f5fd4 ] + +We sometimes observe use-after-free when dereferencing a neighbour [1]. +The problem seems to be that the driver stores a pointer to the +neighbour, but without holding a reference on it. A reference is only +taken when the neighbour is used by a nexthop. + +Fix by simplifying the reference counting scheme. Always take a +reference when storing a neighbour pointer in a neighbour entry. Avoid +taking a referencing when the neighbour is used by a nexthop as the +neighbour entry associated with the nexthop already holds a reference. + +Tested by running the test that uncovered the problem over 300 times. +Without this patch the problem was reproduced after a handful of +iterations. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_neigh_entry_update+0x2d4/0x310 +Read of size 8 at addr ffff88817f8e3420 by task ip/3929 + +CPU: 3 UID: 0 PID: 3929 Comm: ip Not tainted 6.18.0-rc4-virtme-g36b21a067510 #3 PREEMPT(full) +Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 +Call Trace: + + dump_stack_lvl+0x6f/0xa0 + print_address_description.constprop.0+0x6e/0x300 + print_report+0xfc/0x1fb + kasan_report+0xe4/0x110 + mlxsw_sp_neigh_entry_update+0x2d4/0x310 + mlxsw_sp_router_rif_gone_sync+0x35f/0x510 + mlxsw_sp_rif_destroy+0x1ea/0x730 + mlxsw_sp_inetaddr_port_vlan_event+0xa1/0x1b0 + __mlxsw_sp_inetaddr_lag_event+0xcc/0x130 + __mlxsw_sp_inetaddr_event+0xf5/0x3c0 + mlxsw_sp_router_netdevice_event+0x1015/0x1580 + notifier_call_chain+0xcc/0x150 + call_netdevice_notifiers_info+0x7e/0x100 + __netdev_upper_dev_unlink+0x10b/0x210 + netdev_upper_dev_unlink+0x79/0xa0 + vrf_del_slave+0x18/0x50 + do_set_master+0x146/0x7d0 + do_setlink.isra.0+0x9a0/0x2880 + rtnl_newlink+0x637/0xb20 + rtnetlink_rcv_msg+0x6fe/0xb90 + netlink_rcv_skb+0x123/0x380 + netlink_unicast+0x4a3/0x770 + netlink_sendmsg+0x75b/0xc90 + __sock_sendmsg+0xbe/0x160 + ____sys_sendmsg+0x5b2/0x7d0 + ___sys_sendmsg+0xfd/0x180 + __sys_sendmsg+0x124/0x1c0 + do_syscall_64+0xbb/0xfd0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[...] + +Allocated by task 109: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7b/0x90 + __kmalloc_noprof+0x2c1/0x790 + neigh_alloc+0x6af/0x8f0 + ___neigh_create+0x63/0xe90 + mlxsw_sp_nexthop_neigh_init+0x430/0x7e0 + mlxsw_sp_nexthop_type_init+0x212/0x960 + mlxsw_sp_nexthop6_group_info_init.constprop.0+0x81f/0x1280 + mlxsw_sp_nexthop6_group_get+0x392/0x6a0 + mlxsw_sp_fib6_entry_create+0x46a/0xfd0 + mlxsw_sp_router_fib6_replace+0x1ed/0x5f0 + mlxsw_sp_router_fib6_event_work+0x10a/0x2a0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Freed by task 154: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kmem_cache_free_bulk.part.0+0x1eb/0x5e0 + kvfree_rcu_bulk+0x1f2/0x260 + kfree_rcu_work+0x130/0x1b0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Last potentially related work creation: + kasan_save_stack+0x30/0x50 + kasan_record_aux_stack+0x8c/0xa0 + kvfree_call_rcu+0x93/0x5b0 + mlxsw_sp_router_neigh_event_work+0x67d/0x860 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Fixes: 6cf3c971dc84 ("mlxsw: spectrum_router: Add private neigh table") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/92d75e21d95d163a41b5cea67a15cd33f547cba6.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlxsw/spectrum_router.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index d2887ae508bb8..e22ee1336d742 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2032,6 +2032,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + if (!neigh_entry) + return NULL; + ++ neigh_hold(n); + neigh_entry->key.n = n; + neigh_entry->rif = rif; + INIT_LIST_HEAD(&neigh_entry->nexthop_list); +@@ -2041,6 +2042,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + + static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) + { ++ neigh_release(neigh_entry->key.n); + kfree(neigh_entry); + } + +@@ -3607,6 +3609,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + if (err) + goto err_neigh_entry_insert; + ++ neigh_release(old_n); ++ + read_lock_bh(&n->lock); + nud_state = n->nud_state; + dead = n->dead; +@@ -3615,14 +3619,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + + list_for_each_entry(nh, &neigh_entry->nexthop_list, + neigh_list_node) { +- neigh_release(old_n); +- neigh_clone(n); + __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp); + } + +- neigh_release(n); +- + return 0; + + err_neigh_entry_insert: +@@ -3711,6 +3711,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, + } + } + ++ /* Release the reference taken by neigh_lookup() / neigh_create() since ++ * neigh_entry already holds one. ++ */ ++ neigh_release(n); ++ + /* If that is the first nexthop connected to that neigh, add to + * nexthop_neighs_list + */ +@@ -3737,11 +3742,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) + { + struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; +- struct neighbour *n; + + if (!neigh_entry) + return; +- n = neigh_entry->key.n; + + __mlxsw_sp_nexthop_neigh_update(nh, true); + list_del(&nh->neigh_list_node); +@@ -3755,8 +3758,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + + if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) + mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); +- +- neigh_release(n); + } + + static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) +-- +2.51.0 + diff --git a/queue-5.10/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch b/queue-5.10/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch new file mode 100644 index 0000000000..171300d89c --- /dev/null +++ b/queue-5.10/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch @@ -0,0 +1,68 @@ +From 1c819f7cae8d1942df25ca7a960b0769b145daf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Dec 2022 14:48:24 +0300 +Subject: net/ethtool/ioctl: remove if n_stats checks from + ethtool_get_phy_stats + +From: Daniil Tatianin + +[ Upstream commit fd4778581d61d8848b532f8cdc9b325138748437 ] + +Now that we always early return if we don't have any stats we can remove +these checks as they're no longer necessary. + +Signed-off-by: Daniil Tatianin +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index ede11854f493f..8f7efe152a7bb 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2063,28 +2063,24 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + + stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); +- if (!data) +- return -ENOMEM; ++ data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (!data) ++ return -ENOMEM; + +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(phydev, &stats, data); +- if (ret < 0) +- goto out; +- } else { +- ops->get_ethtool_phy_stats(dev, &stats, data); +- } ++ if (phydev && !ops->get_ethtool_phy_stats && ++ phy_ops && phy_ops->get_stats) { ++ ret = phy_ops->get_stats(phydev, &stats, data); ++ if (ret < 0) ++ goto out; + } else { +- data = NULL; ++ ops->get_ethtool_phy_stats(dev, &stats, data); + } + + ret = -EFAULT; + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) + goto out; + ret = 0; + +-- +2.51.0 + diff --git a/queue-5.10/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch b/queue-5.10/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch new file mode 100644 index 0000000000..ba6380656b --- /dev/null +++ b/queue-5.10/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch @@ -0,0 +1,168 @@ +From 2cd5724f1934863927ee58695b4e6ef8d39db658 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Dec 2022 14:48:25 +0300 +Subject: net/ethtool/ioctl: split ethtool_get_phy_stats into multiple helpers + +From: Daniil Tatianin + +[ Upstream commit 201ed315f9676809cd5b20a39206e964106d4f27 ] + +So that it's easier to follow and make sense of the branching and +various conditions. + +Stats retrieval has been split into two separate functions +ethtool_get_phy_stats_phydev & ethtool_get_phy_stats_ethtool. +The former attempts to retrieve the stats using phydev & phy_ops, while +the latter uses ethtool_ops. + +Actual n_stats validation & array allocation has been moved into a new +ethtool_vzalloc_stats_array helper. + +This also fixes a potential NULL dereference of +ops->get_ethtool_phy_stats where it was getting called in an else branch +unconditionally without making sure it was actually present. + +Found by Linux Verification Center (linuxtesting.org) with the SVACE +static analysis tool. + +Signed-off-by: Daniil Tatianin +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 102 ++++++++++++++++++++++++++++++-------------- + 1 file changed, 69 insertions(+), 33 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 8f7efe152a7bb..2ac9cf1c36ba6 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2034,23 +2034,8 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + return ret; + } + +-static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) ++static int ethtool_vzalloc_stats_array(int n_stats, u64 **data) + { +- const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; +- const struct ethtool_ops *ops = dev->ethtool_ops; +- struct phy_device *phydev = dev->phydev; +- struct ethtool_stats stats; +- u64 *data; +- int ret, n_stats; +- +- if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) +- return -EOPNOTSUPP; +- +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_sset_count) +- n_stats = phy_ops->get_sset_count(phydev); +- else +- n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); + if (n_stats < 0) + return n_stats; + if (n_stats > S32_MAX / sizeof(u64)) +@@ -2058,31 +2043,82 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (WARN_ON_ONCE(!n_stats)) + return -EOPNOTSUPP; + ++ *data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (!*data) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, ++ struct ethtool_stats *stats, ++ u64 **data) ++ { ++ const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; ++ int n_stats, ret; ++ ++ if (!phy_ops || !phy_ops->get_sset_count || !phy_ops->get_stats) ++ return -EOPNOTSUPP; ++ ++ n_stats = phy_ops->get_sset_count(phydev); ++ ++ ret = ethtool_vzalloc_stats_array(n_stats, data); ++ if (ret) ++ return ret; ++ ++ stats->n_stats = n_stats; ++ return phy_ops->get_stats(phydev, stats, *data); ++} ++ ++static int ethtool_get_phy_stats_ethtool(struct net_device *dev, ++ struct ethtool_stats *stats, ++ u64 **data) ++{ ++ const struct ethtool_ops *ops = dev->ethtool_ops; ++ int n_stats, ret; ++ ++ if (!ops || !ops->get_sset_count || ops->get_ethtool_phy_stats) ++ return -EOPNOTSUPP; ++ ++ n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ ++ ret = ethtool_vzalloc_stats_array(n_stats, data); ++ if (ret) ++ return ret; ++ ++ stats->n_stats = n_stats; ++ ops->get_ethtool_phy_stats(dev, stats, *data); ++ ++ return 0; ++} ++ ++static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) ++{ ++ struct phy_device *phydev = dev->phydev; ++ struct ethtool_stats stats; ++ u64 *data = NULL; ++ int ret = -EOPNOTSUPP; ++ + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (phydev) ++ ret = ethtool_get_phy_stats_phydev(phydev, &stats, &data); + +- data = vzalloc(array_size(n_stats, sizeof(u64))); +- if (!data) +- return -ENOMEM; ++ if (ret == -EOPNOTSUPP) ++ ret = ethtool_get_phy_stats_ethtool(dev, &stats, &data); + +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(phydev, &stats, data); +- if (ret < 0) +- goto out; +- } else { +- ops->get_ethtool_phy_stats(dev, &stats, data); +- } ++ if (ret) ++ goto out; + +- ret = -EFAULT; +- if (copy_to_user(useraddr, &stats, sizeof(stats))) ++ if (copy_to_user(useraddr, &stats, sizeof(stats))) { ++ ret = -EFAULT; + goto out; ++ } ++ + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) +- goto out; +- ret = 0; ++ if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ ret = -EFAULT; + + out: + vfree(data); +-- +2.51.0 + diff --git a/queue-5.10/net-hns3-add-vlan-id-validation-before-using.patch b/queue-5.10/net-hns3-add-vlan-id-validation-before-using.patch new file mode 100644 index 0000000000..240376e446 --- /dev/null +++ b/queue-5.10/net-hns3-add-vlan-id-validation-before-using.patch @@ -0,0 +1,46 @@ +From f3214cf7129469a5ef2b2ce8f4e235fe8502599c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:37 +0800 +Subject: net: hns3: add VLAN id validation before using + +From: Jian Shen + +[ Upstream commit 6ef935e65902bfed53980ad2754b06a284ea8ac1 ] + +Currently, the VLAN id may be used without validation when +receive a VLAN configuration mailbox from VF. The length of +vlan_del_fail_bmap is BITS_TO_LONGS(VLAN_N_VID). It may cause +out-of-bounds memory access once the VLAN id is bigger than +or equal to VLAN_N_VID. + +Therefore, VLAN id needs to be checked to ensure it is within +the range of VLAN_N_VID. + +Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index aa987cad7cadf..99b5b956ed8f9 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -9196,6 +9196,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, + bool writen_to_tbl = false; + int ret = 0; + ++ if (vlan_id >= VLAN_N_VID) ++ return -EINVAL; ++ + /* When device is resetting or reset failed, firmware is unable to + * handle mailbox. Just record the vlan id, and remove it after + * reset finished. +-- +2.51.0 + diff --git a/queue-5.10/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch b/queue-5.10/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch new file mode 100644 index 0000000000..f44eae13ee --- /dev/null +++ b/queue-5.10/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch @@ -0,0 +1,52 @@ +From 62fae79281a54afa667feed6b29c48e4bb7c20e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:35 +0800 +Subject: net: hns3: using the num_tqps in the vf driver to apply for resources + +From: Jian Shen + +[ Upstream commit c2a16269742e176fccdd0ef9c016a233491a49ad ] + +Currently, hdev->htqp is allocated using hdev->num_tqps, and kinfo->tqp +is allocated using kinfo->num_tqps. However, kinfo->num_tqps is set to +min(new_tqps, hdev->num_tqps); Therefore, kinfo->num_tqps may be smaller +than hdev->num_tqps, which causes some hdev->htqp[i] to remain +uninitialized in hclgevf_knic_setup(). + +Thus, this patch allocates hdev->htqp and kinfo->tqp using hdev->num_tqps, +ensuring that the lengths of hdev->htqp and kinfo->tqp are consistent +and that all elements are properly initialized. + +Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-2-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 15dca78fd736c..98abb47014b75 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -434,12 +434,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) + new_tqps = kinfo->rss_size * num_tc; + kinfo->num_tqps = min(new_tqps, hdev->num_tqps); + +- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, ++ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, + sizeof(struct hnae3_queue *), GFP_KERNEL); + if (!kinfo->tqp) + return -ENOMEM; + +- for (i = 0; i < kinfo->num_tqps; i++) { ++ for (i = 0; i < hdev->num_tqps; i++) { + hdev->htqp[i].q.handle = &hdev->nic; + hdev->htqp[i].q.tqp_index = i; + kinfo->tqp[i] = &hdev->htqp[i].q; +-- +2.51.0 + diff --git a/queue-5.10/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch b/queue-5.10/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch new file mode 100644 index 0000000000..b0a1c04a4e --- /dev/null +++ b/queue-5.10/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch @@ -0,0 +1,94 @@ +From 34852bbc59913ca097789d6305b07d8019a115db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Jan 2023 15:24:19 +0200 +Subject: net/mlx5: fw_tracer, Add support for unrecognized string + +From: Shay Drory + +[ Upstream commit f7133135235dbd11e7cb5fe62fe5d05ce5e82eeb ] + +In case FW is publishing a string which isn't found in the driver's +string DBs, keep the string as raw data. + +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: b35966042d20 ("net/mlx5: fw_tracer, Validate format string parameters") +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 25 +++++++++++++++++-- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index d49fd21f49637..1002bf0078659 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -460,6 +460,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer, + + tracer_event->event_id = MLX5_GET(tracer_event, trace, event_id); + tracer_event->lost_event = MLX5_GET(tracer_event, trace, lost); ++ tracer_event->out = trace; + + switch (tracer_event->event_id) { + case TRACER_EVENT_TYPE_TIMESTAMP: +@@ -582,6 +583,26 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + mlx5_tracer_clean_message(str_frmt); + } + ++static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_event *tracer_event) ++{ ++ struct tracer_string_format *cur_string; ++ ++ cur_string = mlx5_tracer_message_insert(tracer, tracer_event); ++ if (!cur_string) ++ return -1; ++ ++ cur_string->event_id = tracer_event->event_id; ++ cur_string->timestamp = tracer_event->string_event.timestamp; ++ cur_string->lost = tracer_event->lost_event; ++ cur_string->string = "0x%08x%08x"; ++ cur_string->num_of_params = 2; ++ cur_string->params[0] = upper_32_bits(*tracer_event->out); ++ cur_string->params[1] = lower_32_bits(*tracer_event->out); ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++ return 0; ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -590,7 +611,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (tracer_event->string_event.tdsn == 0) { + cur_string = mlx5_tracer_get_string(tracer, tracer_event); + if (!cur_string) +- return -1; ++ return mlx5_tracer_handle_raw_string(tracer, tracer_event); + + cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); + cur_string->last_param_num = 0; +@@ -605,7 +626,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) { + pr_debug("%s Got string event for unknown string tmsn: %d\n", + __func__, tracer_event->string_event.tmsn); +- return -1; ++ return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 97252a85d65e6..568efb1e2bd24 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -158,6 +158,7 @@ struct tracer_event { + struct tracer_string_event string_event; + struct tracer_timestamp_event timestamp_event; + }; ++ u64 *out; + }; + + struct mlx5_ifc_tracer_event_bits { +-- +2.51.0 + diff --git a/queue-5.10/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch b/queue-5.10/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch new file mode 100644 index 0000000000..24eda8855d --- /dev/null +++ b/queue-5.10/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch @@ -0,0 +1,84 @@ +From 49877eefff4e6dad5028cd074f35fd6ea45fd4e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:12 +0200 +Subject: net/mlx5: fw_tracer, Handle escaped percent properly + +From: Shay Drory + +[ Upstream commit c0289f67f7d6a0dfba0e92cfe661a5c70c8c6e92 ] + +The firmware tracer's format string validation and parameter counting +did not properly handle escaped percent signs (%%). This caused +fw_tracer to count more parameters when trace format strings contained +literal percent characters. + +To fix it, allow %% to pass string validation and skip %% sequences when +counting parameters since they represent literal percent signs rather +than format specifiers. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reported-by: Breno Leitao +Reviewed-by: Moshe Shemesh +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 2645e941ef1ce..f3985421e739e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -364,11 +364,11 @@ static bool mlx5_is_valid_spec(const char *str) + while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') + str++; + +- /* Check if it's a valid integer/hex specifier: ++ /* Check if it's a valid integer/hex specifier or %%: + * Valid formats: %x, %d, %i, %u, etc. + */ + if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && +- *str != 'u' && *str != 'c') ++ *str != 'u' && *str != 'c' && *str != '%') + return false; + + return true; +@@ -386,7 +386,11 @@ static bool mlx5_tracer_validate_params(const char *str) + if (!mlx5_is_valid_spec(substr + 1)) + return false; + +- substr = strstr(substr + 1, PARAM_CHAR); ++ if (*(substr + 1) == '%') ++ substr = strstr(substr + 2, PARAM_CHAR); ++ else ++ substr = strstr(substr + 1, PARAM_CHAR); ++ + } + + return true; +@@ -463,11 +467,15 @@ static int mlx5_tracer_get_num_of_params(char *str) + substr = strstr(pstr, VAL_PARM); + } + +- /* count all the % characters */ ++ /* count all the % characters, but skip %% (escaped percent) */ + substr = strstr(str, PARAM_CHAR); + while (substr) { +- num_of_params += 1; +- str = substr + 1; ++ if (*(substr + 1) != '%') { ++ num_of_params += 1; ++ str = substr + 1; ++ } else { ++ str = substr + 2; ++ } + substr = strstr(str, PARAM_CHAR); + } + +-- +2.51.0 + diff --git a/queue-5.10/net-mlx5-fw_tracer-validate-format-string-parameters.patch b/queue-5.10/net-mlx5-fw_tracer-validate-format-string-parameters.patch new file mode 100644 index 0000000000..6b938e1c09 --- /dev/null +++ b/queue-5.10/net-mlx5-fw_tracer-validate-format-string-parameters.patch @@ -0,0 +1,195 @@ +From 7f6e35f7a44526fae5ccf9dcd435fe71f072f37f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:11 +0200 +Subject: net/mlx5: fw_tracer, Validate format string parameters + +From: Shay Drory + +[ Upstream commit b35966042d20b14e2d83330049f77deec5229749 ] + +Add validation for format string parameters in the firmware tracer to +prevent potential security vulnerabilities and crashes from malformed +format strings received from firmware. + +The firmware tracer receives format strings from the device firmware and +uses them to format trace messages. Without proper validation, bad +firmware could provide format strings with invalid format specifiers +(e.g., %s, %p, %n) that could lead to crashes, or other undefined +behavior. + +Add mlx5_tracer_validate_params() to validate that all format specifiers +in trace strings are limited to safe integer/hex formats (%x, %d, %i, +%u, %llx, %lx, etc.). Reject strings containing other format types that +could be used to access arbitrary memory or cause crashes. +Invalid format strings are added to the trace output for visibility with +"BAD_FORMAT: " prefix. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Reported-by: Breno Leitao +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 83 ++++++++++++++++--- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 74 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 1002bf0078659..2645e941ef1ce 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -33,6 +33,7 @@ + #include "lib/eq.h" + #include "fw_tracer.h" + #include "fw_tracer_tracepoint.h" ++#include + + static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) + { +@@ -354,6 +355,43 @@ static const char *VAL_PARM = "%llx"; + static const char *REPLACE_64_VAL_PARM = "%x%x"; + static const char *PARAM_CHAR = "%"; + ++static bool mlx5_is_valid_spec(const char *str) ++{ ++ /* Parse format specifiers to find the actual type. ++ * Structure: %[flags][width][.precision][length]type ++ * Skip flags, width, precision & length. ++ */ ++ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') ++ str++; ++ ++ /* Check if it's a valid integer/hex specifier: ++ * Valid formats: %x, %d, %i, %u, etc. ++ */ ++ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && ++ *str != 'u' && *str != 'c') ++ return false; ++ ++ return true; ++} ++ ++static bool mlx5_tracer_validate_params(const char *str) ++{ ++ const char *substr = str; ++ ++ if (!str) ++ return false; ++ ++ substr = strstr(substr, PARAM_CHAR); ++ while (substr) { ++ if (!mlx5_is_valid_spec(substr + 1)) ++ return false; ++ ++ substr = strstr(substr + 1, PARAM_CHAR); ++ } ++ ++ return true; ++} ++ + static int mlx5_tracer_message_hash(u32 message_id) + { + return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); +@@ -413,6 +451,10 @@ static int mlx5_tracer_get_num_of_params(char *str) + char *substr, *pstr = str; + int num_of_params = 0; + ++ /* Validate that all parameters are valid before processing */ ++ if (!mlx5_tracer_validate_params(str)) ++ return -EINVAL; ++ + /* replace %llx with %x%x */ + substr = strstr(pstr, VAL_PARM); + while (substr) { +@@ -564,14 +606,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + { + char tmp[512]; + +- snprintf(tmp, sizeof(tmp), str_frmt->string, +- str_frmt->params[0], +- str_frmt->params[1], +- str_frmt->params[2], +- str_frmt->params[3], +- str_frmt->params[4], +- str_frmt->params[5], +- str_frmt->params[6]); ++ if (str_frmt->invalid_string) ++ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string); ++ else ++ snprintf(tmp, sizeof(tmp), str_frmt->string, ++ str_frmt->params[0], ++ str_frmt->params[1], ++ str_frmt->params[2], ++ str_frmt->params[3], ++ str_frmt->params[4], ++ str_frmt->params[5], ++ str_frmt->params[6]); + + trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, + str_frmt->event_id, tmp); +@@ -603,6 +648,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, + return 0; + } + ++static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_string_format *cur_string) ++{ ++ cur_string->invalid_string = true; ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -613,12 +665,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + +- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); +- cur_string->last_param_num = 0; + cur_string->event_id = tracer_event->event_id; + cur_string->tmsn = tracer_event->string_event.tmsn; + cur_string->timestamp = tracer_event->string_event.timestamp; + cur_string->lost = tracer_event->lost_event; ++ cur_string->last_param_num = 0; ++ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s Invalid format string parameters\n", ++ __func__); ++ mlx5_tracer_handle_bad_format_string(tracer, cur_string); ++ return 0; ++ } + if (cur_string->num_of_params == 0) /* trace with no params */ + list_add_tail(&cur_string->list, &tracer->ready_strings_list); + } else { +@@ -628,6 +686,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + __func__, tracer_event->string_event.tmsn); + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s string parameter of invalid string, dumping\n", ++ __func__); ++ return 0; ++ } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { + pr_debug("%s Number of params exceeds the max (%d)\n", +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 568efb1e2bd24..603ef441f1b21 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -117,6 +117,7 @@ struct tracer_string_format { + struct list_head list; + u32 timestamp; + bool lost; ++ bool invalid_string; + }; + + enum mlx5_fw_tracer_ownership_state { +-- +2.51.0 + diff --git a/queue-5.10/net-openvswitch-fix-middle-attribute-validation-in-p.patch b/queue-5.10/net-openvswitch-fix-middle-attribute-validation-in-p.patch new file mode 100644 index 0000000000..28c21af32c --- /dev/null +++ b/queue-5.10/net-openvswitch-fix-middle-attribute-validation-in-p.patch @@ -0,0 +1,112 @@ +From 8dd47ec012adc795feb2a2b303c91a2d4aaad279 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:53:32 +0100 +Subject: net: openvswitch: fix middle attribute validation in push_nsh() + action + +From: Ilya Maximets + +[ Upstream commit 5ace7ef87f059d68b5f50837ef3e8a1a4870c36e ] + +The push_nsh() action structure looks like this: + + OVS_ACTION_ATTR_PUSH_NSH(OVS_KEY_ATTR_NSH(OVS_NSH_KEY_ATTR_BASE,...)) + +The outermost OVS_ACTION_ATTR_PUSH_NSH attribute is OK'ed by the +nla_for_each_nested() inside __ovs_nla_copy_actions(). The innermost +OVS_NSH_KEY_ATTR_BASE/MD1/MD2 are OK'ed by the nla_for_each_nested() +inside nsh_key_put_from_nlattr(). But nothing checks if the attribute +in the middle is OK. We don't even check that this attribute is the +OVS_KEY_ATTR_NSH. We just do a double unwrap with a pair of nla_data() +calls - first time directly while calling validate_push_nsh() and the +second time as part of the nla_for_each_nested() macro, which isn't +safe, potentially causing invalid memory access if the size of this +attribute is incorrect. The failure may not be noticed during +validation due to larger netlink buffer, but cause trouble later during +action execution where the buffer is allocated exactly to the size: + + BUG: KASAN: slab-out-of-bounds in nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + Read of size 184 at addr ffff88816459a634 by task a.out/22624 + + CPU: 8 UID: 0 PID: 22624 6.18.0-rc7+ #115 PREEMPT(voluntary) + Call Trace: + + dump_stack_lvl+0x51/0x70 + print_address_description.constprop.0+0x2c/0x390 + kasan_report+0xdd/0x110 + kasan_check_range+0x35/0x1b0 + __asan_memcpy+0x20/0x60 + nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + push_nsh+0x82/0x120 [openvswitch] + do_execute_actions+0x1405/0x2840 [openvswitch] + ovs_execute_actions+0xd5/0x3b0 [openvswitch] + ovs_packet_cmd_execute+0x949/0xdb0 [openvswitch] + genl_family_rcv_msg_doit+0x1d6/0x2b0 + genl_family_rcv_msg+0x336/0x580 + genl_rcv_msg+0x9f/0x130 + netlink_rcv_skb+0x11f/0x370 + genl_rcv+0x24/0x40 + netlink_unicast+0x73e/0xaa0 + netlink_sendmsg+0x744/0xbf0 + __sys_sendto+0x3d6/0x450 + do_syscall_64+0x79/0x2c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + +Let's add some checks that the attribute is properly sized and it's +the only one attribute inside the action. Technically, there is no +real reason for OVS_KEY_ATTR_NSH to be there, as we know that we're +pushing an NSH header already, it just creates extra nesting, but +that's how uAPI works today. So, keeping as it is. + +Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") +Reported-by: Junvy Yang +Signed-off-by: Ilya Maximets +Acked-by: Eelco Chaudron echaudro@redhat.com +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20251204105334.900379-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index a70a87a4392ab..54f952620b214 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2760,13 +2760,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, + return err; + } + +-static bool validate_push_nsh(const struct nlattr *attr, bool log) ++static bool validate_push_nsh(const struct nlattr *a, bool log) + { ++ struct nlattr *nsh_key = nla_data(a); + struct sw_flow_match match; + struct sw_flow_key key; + ++ /* There must be one and only one NSH header. */ ++ if (!nla_ok(nsh_key, nla_len(a)) || ++ nla_total_size(nla_len(nsh_key)) != nla_len(a) || ++ nla_type(nsh_key) != OVS_KEY_ATTR_NSH) ++ return false; ++ + ovs_match_init(&match, &key, true, NULL); +- return !nsh_key_put_from_nlattr(attr, &match, false, true, log); ++ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log); + } + + /* Return false if there are any non-masked bits set. +@@ -3320,7 +3327,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, + return -EINVAL; + } + mac_proto = MAC_PROTO_NONE; +- if (!validate_push_nsh(nla_data(a), log)) ++ if (!validate_push_nsh(a, log)) + return -EINVAL; + break; + +-- +2.51.0 + diff --git a/queue-5.10/net-sched-ets-always-remove-class-from-active-list-b.patch b/queue-5.10/net-sched-ets-always-remove-class-from-active-list-b.patch new file mode 100644 index 0000000000..5f4f2373e7 --- /dev/null +++ b/queue-5.10/net-sched-ets-always-remove-class-from-active-list-b.patch @@ -0,0 +1,232 @@ +From 778fe98c6c46e3d8a512fa31fe37b72cf4786f43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: net/sched: ets: Always remove class from active list before deleting + in ets_qdisc_change + +From: Jamal Hadi Salim + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index e38879e598721..ad5d9b27670ca 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -665,7 +665,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.51.0 + diff --git a/queue-5.10/net-sched-ets-remove-drr-class-from-the-active-list-.patch b/queue-5.10/net-sched-ets-remove-drr-class-from-the-active-list-.patch new file mode 100644 index 0000000000..fc56dead65 --- /dev/null +++ b/queue-5.10/net-sched-ets-remove-drr-class-from-the-active-list-.patch @@ -0,0 +1,88 @@ +From af368b80f80b362be4df8bb84b83a021b6fb30a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:01:24 -0300 +Subject: net/sched: ets: Remove drr class from the active list if it changes + to strict + +From: Victor Nogueira + +[ Upstream commit b1e125ae425aba9b45252e933ca8df52a843ec70 ] + +Whenever a user issues an ets qdisc change command, transforming a +drr class into a strict one, the ets code isn't checking whether that +class was in the active list and removing it. This means that, if a +user changes a strict class (which was in the active list) back to a drr +one, that class will be added twice to the active list [1]. + +Doing so with the following commands: + +tc qdisc add dev lo root handle 1: ets bands 2 strict 1 +tc qdisc add dev lo parent 1:2 handle 20: \ + tbf rate 8bit burst 100b latency 1s +tc filter add dev lo parent 1: basic classid 1:2 +ping -c1 -W0.01 -s 56 127.0.0.1 +tc qdisc change dev lo root handle 1: ets bands 2 strict 2 +tc qdisc change dev lo root handle 1: ets bands 2 strict 1 +ping -c1 -W0.01 -s 56 127.0.0.1 + +Will trigger the following splat with list debug turned on: + +[ 59.279014][ T365] ------------[ cut here ]------------ +[ 59.279452][ T365] list_add double add: new=ffff88801d60e350, prev=ffff88801d60e350, next=ffff88801d60e2c0. +[ 59.280153][ T365] WARNING: CPU: 3 PID: 365 at lib/list_debug.c:35 __list_add_valid_or_report+0x17f/0x220 +[ 59.280860][ T365] Modules linked in: +[ 59.281165][ T365] CPU: 3 UID: 0 PID: 365 Comm: tc Not tainted 6.18.0-rc7-00105-g7e9f13163c13-dirty #239 PREEMPT(voluntary) +[ 59.281977][ T365] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 59.282391][ T365] RIP: 0010:__list_add_valid_or_report+0x17f/0x220 +[ 59.282842][ T365] Code: 89 c6 e8 d4 b7 0d ff 90 0f 0b 90 90 31 c0 e9 31 ff ff ff 90 48 c7 c7 e0 a0 22 9f 48 89 f2 48 89 c1 4c 89 c6 e8 b2 b7 0d ff 90 <0f> 0b 90 90 31 c0 e9 0f ff ff ff 48 89 f7 48 89 44 24 10 4c 89 44 +... +[ 59.288812][ T365] Call Trace: +[ 59.289056][ T365] +[ 59.289224][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.289546][ T365] ets_qdisc_change+0xd2b/0x1e80 +[ 59.289891][ T365] ? __lock_acquire+0x7e7/0x1be0 +[ 59.290223][ T365] ? __pfx_ets_qdisc_change+0x10/0x10 +[ 59.290546][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.290898][ T365] ? __mutex_trylock_common+0xda/0x240 +[ 59.291228][ T365] ? __pfx___mutex_trylock_common+0x10/0x10 +[ 59.291655][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.291993][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.292313][ T365] ? trace_contention_end+0xc8/0x110 +[ 59.292656][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293022][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293351][ T365] tc_modify_qdisc+0x63a/0x1cf0 + +Fix this by always checking and removing an ets class from the active list +when changing it to strict. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/net/sched/sch_ets.c?id=ce052b9402e461a9aded599f5b47e76bc727f7de#n663 + +Fixes: cd9b50adc6bb9 ("net/sched: ets: fix crash when flipping from 'strict' to 'quantum'") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Reviewed-by: Petr Machata +Link: https://patch.msgid.link/20251208190125.1868423-1-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index ad5d9b27670ca..c939937b2b81d 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -677,6 +677,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nstrict; i < nstrict; i++) { ++ if (cl_is_active(&q->classes[i])) ++ list_del_init(&q->classes[i].alist); ++ } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + +-- +2.51.0 + diff --git a/queue-5.10/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch b/queue-5.10/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch new file mode 100644 index 0000000000..56de348162 --- /dev/null +++ b/queue-5.10/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch @@ -0,0 +1,90 @@ +From b7c3ff131dadb9d5c10dc1b0375fa46406d91eaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 12:58:01 +0100 +Subject: netfilter: nf_conncount: fix leaked ct in error paths + +From: Fernando Fernandez Mancera + +[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ] + +There are some situations where ct might be leaked as error paths are +skipping the refcounted check and return immediately. In order to solve +it make sure that the check is always called. + +Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conncount.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index 97b631a81484d..c00b8e522c5a7 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net, + struct nf_conn *found_ct; + unsigned int collect = 0; + bool refcounted = false; ++ int err = 0; + + if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- if (refcounted) +- nf_ct_put(ct); +- return -EEXIST; ++ err = -EEXIST; ++ goto out_put; + } + + if ((u32)jiffies == list->last_gc) +@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net, + } + + add_new_node: +- if (WARN_ON_ONCE(list->count > INT_MAX)) +- return -EOVERFLOW; ++ if (WARN_ON_ONCE(list->count > INT_MAX)) { ++ err = -EOVERFLOW; ++ goto out_put; ++ } + + conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); +- if (conn == NULL) +- return -ENOMEM; ++ if (conn == NULL) { ++ err = -ENOMEM; ++ goto out_put; ++ } + + conn->tuple = tuple; + conn->zone = *zone; +@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net, + out_put: + if (refcounted) + nf_ct_put(ct); +- return 0; ++ return err; + } + + int nf_conncount_add_skb(struct net *net, +@@ -446,11 +450,10 @@ insert_tree(struct net *net, + + rb_link_node_rcu(&rbconn->node, parent, rbnode); + rb_insert_color(&rbconn->node, root); +- +- if (refcounted) +- nf_ct_put(ct); + } + out_unlock: ++ if (refcounted) ++ nf_ct_put(ct); + spin_unlock_bh(&nf_conncount_locks[hash]); + return count; + } +-- +2.51.0 + diff --git a/queue-5.10/netrom-fix-memory-leak-in-nr_sendmsg.patch b/queue-5.10/netrom-fix-memory-leak-in-nr_sendmsg.patch new file mode 100644 index 0000000000..a24faad153 --- /dev/null +++ b/queue-5.10/netrom-fix-memory-leak-in-nr_sendmsg.patch @@ -0,0 +1,74 @@ +From b04e00f4169f12c2a86649a321daef741a2630b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 12:13:15 +0800 +Subject: netrom: Fix memory leak in nr_sendmsg() + +From: Wang Liang + +[ Upstream commit 613d12dd794e078be8ff3cf6b62a6b9acf7f4619 ] + +syzbot reported a memory leak [1]. + +When function sock_alloc_send_skb() return NULL in nr_output(), the +original skb is not freed, which was allocated in nr_sendmsg(). Fix this +by freeing it before return. + +[1] +BUG: memory leak +unreferenced object 0xffff888129f35500 (size 240): + comm "syz.0.17", pid 6119, jiffies 4294944652 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 10 52 28 81 88 ff ff ..........R(.... + backtrace (crc 1456a3e4): + kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline] + slab_post_alloc_hook mm/slub.c:4983 [inline] + slab_alloc_node mm/slub.c:5288 [inline] + kmem_cache_alloc_node_noprof+0x36f/0x5e0 mm/slub.c:5340 + __alloc_skb+0x203/0x240 net/core/skbuff.c:660 + alloc_skb include/linux/skbuff.h:1383 [inline] + alloc_skb_with_frags+0x69/0x3f0 net/core/skbuff.c:6671 + sock_alloc_send_pskb+0x379/0x3e0 net/core/sock.c:2965 + sock_alloc_send_skb include/net/sock.h:1859 [inline] + nr_sendmsg+0x287/0x450 net/netrom/af_netrom.c:1105 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg net/socket.c:742 [inline] + sock_write_iter+0x293/0x2a0 net/socket.c:1195 + new_sync_write fs/read_write.c:593 [inline] + vfs_write+0x45d/0x710 fs/read_write.c:686 + ksys_write+0x143/0x170 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xa4/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7abc36bbbb6d7d40b58 +Tested-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20251129041315.1550766-1-wangliang74@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_out.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 5e531394a724b..2b3cbceb0b52d 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) + frontlen = skb_headroom(skb); + + while (skb->len > 0) { +- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) ++ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) { ++ kfree_skb(skb); + return; ++ } + + skb_reserve(skbn, frontlen); + +-- +2.51.0 + diff --git a/queue-5.10/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch b/queue-5.10/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch new file mode 100644 index 0000000000..9e05ce5662 --- /dev/null +++ b/queue-5.10/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch @@ -0,0 +1,37 @@ +From 52bd2b74377d27ca2604ff4fba2fcdda1734dcaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 09:56:39 +0300 +Subject: nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() + +From: Dan Carpenter + +[ Upstream commit 885bebac9909994050bbbeed0829c727e42bd1b7 ] + +Set the error code if "transferred != sizeof(cmd)" instead of +returning success. + +Fixes: dbafc28955fa ("NFC: pn533: don't send USB data off of the stack") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aTfIJ9tZPmeUF4W1@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c +index 68eb1253f888f..77ada0a5c7396 100644 +--- a/drivers/nfc/pn533/usb.c ++++ b/drivers/nfc/pn533/usb.c +@@ -411,7 +411,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) + if (rc || (transferred != sizeof(cmd))) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); +- return rc; ++ return rc ?: -EINVAL; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); +-- +2.51.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 0c8cddee51..4be0beb758 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -165,3 +165,24 @@ hfsplus-verify-inode-mode-when-loading-from-disk.patch hfsplus-fix-volume-corruption-issue-for-generic-073.patch btrfs-scrub-always-update-btrfs_scrub_progress-last_.patch bluetooth-btusb-add-new-vid-pid-13d3-3533-for-rtl882.patch +netrom-fix-memory-leak-in-nr_sendmsg.patch +net-sched-ets-always-remove-class-from-active-list-b.patch +ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch +mlxsw-spectrum_router-fix-neighbour-use-after-free.patch +mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch +net-openvswitch-fix-middle-attribute-validation-in-p.patch +broadcom-b44-prevent-uninitialized-value-usage.patch +netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch +ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch +caif-fix-integer-underflow-in-cffrml_receive.patch +net-sched-ets-remove-drr-class-from-the-active-list-.patch +nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch +ethtool-use-phydev-variable.patch +net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch +net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch +ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch +net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch +net-mlx5-fw_tracer-validate-format-string-parameters.patch +net-mlx5-fw_tracer-handle-escaped-percent-properly.patch +net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch +net-hns3-add-vlan-id-validation-before-using.patch diff --git a/queue-5.15/broadcom-b44-prevent-uninitialized-value-usage.patch b/queue-5.15/broadcom-b44-prevent-uninitialized-value-usage.patch new file mode 100644 index 0000000000..b15c2357f7 --- /dev/null +++ b/queue-5.15/broadcom-b44-prevent-uninitialized-value-usage.patch @@ -0,0 +1,45 @@ +From 73dea7e08bd4a84a3e3410ed607fe360182f0baf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 18:58:16 +0300 +Subject: broadcom: b44: prevent uninitialized value usage + +From: Alexey Simakov + +[ Upstream commit 50b3db3e11864cb4e18ff099cfb38e11e7f87a68 ] + +On execution path with raised B44_FLAG_EXTERNAL_PHY, b44_readphy() +leaves bmcr value uninitialized and it is used later in the code. + +Add check of this flag at the beginning of the b44_nway_reset() and +exit early of the function with restarting autonegotiation if an +external PHY is used. + +Fixes: 753f492093da ("[B44]: port to native ssb support") +Reviewed-by: Jonas Gorski +Reviewed-by: Andrew Lunn +Signed-off-by: Alexey Simakov +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20251205155815.4348-1-bigalex934@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/b44.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c +index ce370ef641f01..3c4e0a78b8a03 100644 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -1811,6 +1811,9 @@ static int b44_nway_reset(struct net_device *dev) + u32 bmcr; + int r; + ++ if (bp->flags & B44_FLAG_EXTERNAL_PHY) ++ return phy_ethtool_nway_reset(dev); ++ + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); +-- +2.51.0 + diff --git a/queue-5.15/caif-fix-integer-underflow-in-cffrml_receive.patch b/queue-5.15/caif-fix-integer-underflow-in-cffrml_receive.patch new file mode 100644 index 0000000000..239abcee7b --- /dev/null +++ b/queue-5.15/caif-fix-integer-underflow-in-cffrml_receive.patch @@ -0,0 +1,58 @@ +From de419bc3edb298921a4dfdf3a91a808a87b4ceda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 21:30:47 +0800 +Subject: caif: fix integer underflow in cffrml_receive() + +From: Junrui Luo + +[ Upstream commit 8a11ff0948b5ad09b71896b7ccc850625f9878d1 ] + +The cffrml_receive() function extracts a length field from the packet +header and, when FCS is disabled, subtracts 2 from this length without +validating that len >= 2. + +If an attacker sends a malicious packet with a length field of 0 or 1 +to an interface with FCS disabled, the subtraction causes an integer +underflow. + +This can lead to memory exhaustion and kernel instability, potential +information disclosure if padding contains uninitialized kernel memory. + +Fix this by validating that len >= 2 before performing the subtraction. + +Reported-by: Yuhao Jiang +Reported-by: Junrui Luo +Fixes: b482cd2053e3 ("net-caif: add CAIF core protocol stack") +Signed-off-by: Junrui Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/SYBPR01MB7881511122BAFEA8212A1608AFA6A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/caif/cffrml.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c +index 6651a8dc62e04..d4d63586053ad 100644 +--- a/net/caif/cffrml.c ++++ b/net/caif/cffrml.c +@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) + len = le16_to_cpu(tmp); + + /* Subtract for FCS on length if FCS is not used. */ +- if (!this->dofcs) ++ if (!this->dofcs) { ++ if (len < 2) { ++ ++cffrml_rcv_error; ++ pr_err("Invalid frame length (%d)\n", len); ++ cfpkt_destroy(pkt); ++ return -EPROTO; ++ } + len -= 2; ++ } + + if (cfpkt_setlen(pkt, len) < 0) { + ++cffrml_rcv_error; +-- +2.51.0 + diff --git a/queue-5.15/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch b/queue-5.15/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch new file mode 100644 index 0000000000..176e5e1a50 --- /dev/null +++ b/queue-5.15/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch @@ -0,0 +1,159 @@ +From f56ee536611f9623a54a31aa282f317031a46c5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 14:19:01 +0200 +Subject: ethtool: Avoid overflowing userspace buffer on stats query + +From: Gal Pressman + +[ Upstream commit 7b07be1ff1cb6c49869910518650e8d0abc7d25f ] + +The ethtool -S command operates across three ioctl calls: +ETHTOOL_GSSET_INFO for the size, ETHTOOL_GSTRINGS for the names, and +ETHTOOL_GSTATS for the values. + +If the number of stats changes between these calls (e.g., due to device +reconfiguration), userspace's buffer allocation will be incorrect, +potentially leading to buffer overflow. + +Drivers are generally expected to maintain stable stat counts, but some +drivers (e.g., mlx5, bnx2x, bna, ksz884x) use dynamic counters, making +this scenario possible. + +Some drivers try to handle this internally: +- bnad_get_ethtool_stats() returns early in case stats.n_stats is not + equal to the driver's stats count. +- micrel/ksz884x also makes sure not to write anything beyond + stats.n_stats and overflow the buffer. + +However, both use stats.n_stats which is already assigned with the value +returned from get_sset_count(), hence won't solve the issue described +here. + +Change ethtool_get_strings(), ethtool_get_stats(), +ethtool_get_phy_stats() to not return anything in case of a mismatch +between userspace's size and get_sset_size(), to prevent buffer +overflow. +The returned n_stats value will be equal to zero, to reflect that +nothing has been returned. + +This could result in one of two cases when using upstream ethtool, +depending on when the size change is detected: +1. When detected in ethtool_get_strings(): + # ethtool -S eth2 + no stats available + +2. When detected in get stats, all stats will be reported as zero. + +Both cases are presumably transient, and a subsequent ethtool call +should succeed. + +Other than the overflow avoidance, these two cases are very evident (no +output/cleared stats), which is arguably better than presenting +incorrect/shifted stats. +I also considered returning an error instead of a "silent" response, but +that seems more destructive towards userspace apps. + +Notes: +- This patch does not claim to fix the inherent race, it only makes sure + that we do not overflow the userspace buffer, and makes for a more + predictable behavior. + +- RTNL lock is held during each ioctl, the race window exists between + the separate ioctl calls when the lock is released. + +- Userspace ethtool always fills stats.n_stats, but it is likely that + these stats ioctls are implemented in other userspace applications + which might not fill it. The added code checks that it's not zero, + to prevent any regressions. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Dragos Tatulea +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Link: https://patch.msgid.link/20251208121901.3203692-1-gal@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 33b5c3d8f2f7f..81fe585ddfa91 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1919,7 +1919,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + return -ENOMEM; + WARN_ON_ONCE(!ret); + +- gstrings.len = ret; ++ if (gstrings.len && gstrings.len != ret) ++ gstrings.len = 0; ++ else ++ gstrings.len = ret; + + if (gstrings.len) { + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); +@@ -2032,10 +2035,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (stats.n_stats && stats.n_stats != n_stats) ++ stats.n_stats = 0; ++ else ++ stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (stats.n_stats) { ++ data = vzalloc(array_size(stats.n_stats, sizeof(u64))); + if (!data) + return -ENOMEM; + ops->get_ethtool_stats(dev, &stats, data); +@@ -2047,7 +2053,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + goto out; + ret = 0; + +@@ -2083,6 +2091,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, + return -EOPNOTSUPP; + + n_stats = phy_ops->get_sset_count(phydev); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2103,6 +2115,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev, + return -EOPNOTSUPP; + + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2139,7 +2155,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + } + + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + ret = -EFAULT; + + out: +-- +2.51.0 + diff --git a/queue-5.15/ethtool-use-phydev-variable.patch b/queue-5.15/ethtool-use-phydev-variable.patch new file mode 100644 index 0000000000..878d53146a --- /dev/null +++ b/queue-5.15/ethtool-use-phydev-variable.patch @@ -0,0 +1,53 @@ +From 725a9c3badcf642fc66596959d6efbe4afa86497 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jan 2022 06:10:20 -0800 +Subject: ethtool: use phydev variable + +From: Tom Rix + +[ Upstream commit ccd21ec5b8dd9b8a528a70315cee95fc1dd79d20 ] + +In ethtool_get_phy_stats(), the phydev varaible is set to +dev->phydev but dev->phydev is still used. Replace +dev->phydev uses with phydev. + +Signed-off-by: Tom Rix +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 1e9e70a633d1c..4b736385912ef 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2068,9 +2068,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) + return -EOPNOTSUPP; + +- if (dev->phydev && !ops->get_ethtool_phy_stats && ++ if (phydev && !ops->get_ethtool_phy_stats && + phy_ops && phy_ops->get_sset_count) +- n_stats = phy_ops->get_sset_count(dev->phydev); ++ n_stats = phy_ops->get_sset_count(phydev); + else + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); + if (n_stats < 0) +@@ -2090,9 +2090,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (!data) + return -ENOMEM; + +- if (dev->phydev && !ops->get_ethtool_phy_stats && ++ if (phydev && !ops->get_ethtool_phy_stats && + phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(dev->phydev, &stats, data); ++ ret = phy_ops->get_stats(phydev, &stats, data); + if (ret < 0) + goto out; + } else { +-- +2.51.0 + diff --git a/queue-5.15/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch b/queue-5.15/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch new file mode 100644 index 0000000000..580639027f --- /dev/null +++ b/queue-5.15/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch @@ -0,0 +1,48 @@ +From e481179da9ea05144185e378c4dc4fa1e2d7715f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 13:39:03 +0300 +Subject: ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() + +From: Dmitry Skorodumov + +[ Upstream commit 0c57ff008a11f24f7f05fa760222692a00465fec ] + +Packets with pkt_type == PACKET_LOOPBACK are captured by +handle_frame() function, but they don't have L2 header. +We should not process them in handle_mode_l2(). + +This doesn't affect old L2 functionality, since handling +was anyway incorrect. + +Handle them the same way as in br_handle_frame(): +just pass the skb. + +To observe invalid behaviour, just start "ping -b" on bcast address +of port-interface. + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Signed-off-by: Dmitry Skorodumov +Link: https://patch.msgid.link/20251202103906.4087675-1-skorodumov.dmitry@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index a18b49db38ee0..35ec6d1af6ea6 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -725,6 +725,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + ++ if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) ++ return RX_HANDLER_PASS; ++ + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-5.15/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch b/queue-5.15/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch new file mode 100644 index 0000000000..2b6fd7638e --- /dev/null +++ b/queue-5.15/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch @@ -0,0 +1,80 @@ +From 616c94098342374bd68709208f465ee6639edb7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 16:52:13 +0800 +Subject: ipvs: fix ipv4 null-ptr-deref in route error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Slavin Liu + +[ Upstream commit ad891bb3d079a46a821bf2b8867854645191bab0 ] + +The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure() +without ensuring skb->dev is set, leading to a NULL pointer dereference +in fib_compute_spec_dst() when ipv4_link_failure() attempts to send +ICMP destination unreachable messages. + +The issue emerged after commit ed0de45a1008 ("ipv4: recompile ip options +in ipv4_link_failure") started calling __ip_options_compile() from +ipv4_link_failure(). This code path eventually calls fib_compute_spec_dst() +which dereferences skb->dev. An attempt was made to fix the NULL skb->dev +dereference in commit 0113d9c9d1cc ("ipv4: fix null-deref in +ipv4_link_failure"), but it only addressed the immediate dev_net(skb->dev) +dereference by using a fallback device. The fix was incomplete because +fib_compute_spec_dst() later in the call chain still accesses skb->dev +directly, which remains NULL when IPVS calls dst_link_failure(). + +The crash occurs when: +1. IPVS processes a packet in NAT mode with a misconfigured destination +2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route +3. The error path calls dst_link_failure(skb) with skb->dev == NULL +4. ipv4_link_failure() → ipv4_send_dest_unreach() → + __ip_options_compile() → fib_compute_spec_dst() +5. fib_compute_spec_dst() dereferences NULL skb->dev + +Apply the same fix used for IPv6 in commit 326bf17ea5d4 ("ipvs: fix +ipv6 route unreach panic"): set skb->dev from skb_dst(skb)->dev before +calling dst_link_failure(). + +KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f] +CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2 +RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233 +RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285 +Call Trace: + + spec_dst_fill net/ipv4/ip_options.c:232 + spec_dst_fill net/ipv4/ip_options.c:229 + __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330 + ipv4_send_dest_unreach net/ipv4/route.c:1252 + ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265 + dst_link_failure include/net/dst.h:437 + __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412 + ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764 + +Fixes: ed0de45a1008 ("ipv4: recompile ip options in ipv4_link_failure") +Signed-off-by: Slavin Liu +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/ipvs/ip_vs_xmit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index c87dbc8970023..f82834349ca2c 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -420,6 +420,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + return -1; + + err_unreach: ++ if (!skb->dev) ++ skb->dev = skb_dst(skb)->dev; ++ + dst_link_failure(skb); + return -1; + } +-- +2.51.0 + diff --git a/queue-5.15/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch b/queue-5.15/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch new file mode 100644 index 0000000000..5e483cedfb --- /dev/null +++ b/queue-5.15/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch @@ -0,0 +1,96 @@ +From 0b93b10f68bbd13247b538ad4648d2062a08c578 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:13 +0100 +Subject: mlxsw: spectrum_mr: Fix use-after-free when updating multicast route + stats + +From: Ido Schimmel + +[ Upstream commit 8ac1dacec458f55f871f7153242ed6ab60373b90 ] + +Cited commit added a dedicated mutex (instead of RTNL) to protect the +multicast route list, so that it will not change while the driver +periodically traverses it in order to update the kernel about multicast +route stats that were queried from the device. + +One instance of list entry deletion (during route replace) was missed +and it can result in a use-after-free [1]. + +Fix by acquiring the mutex before deleting the entry from the list and +releasing it afterwards. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] +Read of size 8 at addr ffff8881523c2fa8 by task kworker/2:5/22043 + +CPU: 2 UID: 0 PID: 22043 Comm: kworker/2:5 Not tainted 6.18.0-rc1-custom-g1a3d6d7cd014 #1 PREEMPT(full) +Hardware name: Mellanox Technologies Ltd. MSN2010/SA002610, BIOS 5.6.5 08/24/2017 +Workqueue: mlxsw_core mlxsw_sp_mr_stats_update [mlxsw_spectrum] +Call Trace: + + dump_stack_lvl+0xba/0x110 + print_report+0x174/0x4f5 + kasan_report+0xdf/0x110 + mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + mlxsw_sp_mr_route_add+0xd8/0x4770 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x43/0x70 + kfree+0x14e/0x700 + mlxsw_sp_mr_route_add+0x2dea/0x4770 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:444 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Fixes: f38656d06725 ("mlxsw: spectrum_mr: Protect multicast route list with a lock") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/f996feecfd59fde297964bfc85040b6d83ec6089.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +index 1f6bc0c7e91dd..c39aca54a0d6b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table, + rhashtable_remove_fast(&mr_table->route_ht, + &mr_orig_route->ht_node, + mlxsw_sp_mr_route_ht_params); ++ mutex_lock(&mr_table->route_list_lock); + list_del(&mr_orig_route->node); ++ mutex_unlock(&mr_table->route_list_lock); + mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); + } + +-- +2.51.0 + diff --git a/queue-5.15/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch b/queue-5.15/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch new file mode 100644 index 0000000000..b93d70c263 --- /dev/null +++ b/queue-5.15/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch @@ -0,0 +1,199 @@ +From 6d6359e423a6ffe4affae1affbb2c36286595733 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:12 +0100 +Subject: mlxsw: spectrum_router: Fix neighbour use-after-free + +From: Ido Schimmel + +[ Upstream commit 8b0e69763ef948fb872a7767df4be665d18f5fd4 ] + +We sometimes observe use-after-free when dereferencing a neighbour [1]. +The problem seems to be that the driver stores a pointer to the +neighbour, but without holding a reference on it. A reference is only +taken when the neighbour is used by a nexthop. + +Fix by simplifying the reference counting scheme. Always take a +reference when storing a neighbour pointer in a neighbour entry. Avoid +taking a referencing when the neighbour is used by a nexthop as the +neighbour entry associated with the nexthop already holds a reference. + +Tested by running the test that uncovered the problem over 300 times. +Without this patch the problem was reproduced after a handful of +iterations. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_neigh_entry_update+0x2d4/0x310 +Read of size 8 at addr ffff88817f8e3420 by task ip/3929 + +CPU: 3 UID: 0 PID: 3929 Comm: ip Not tainted 6.18.0-rc4-virtme-g36b21a067510 #3 PREEMPT(full) +Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 +Call Trace: + + dump_stack_lvl+0x6f/0xa0 + print_address_description.constprop.0+0x6e/0x300 + print_report+0xfc/0x1fb + kasan_report+0xe4/0x110 + mlxsw_sp_neigh_entry_update+0x2d4/0x310 + mlxsw_sp_router_rif_gone_sync+0x35f/0x510 + mlxsw_sp_rif_destroy+0x1ea/0x730 + mlxsw_sp_inetaddr_port_vlan_event+0xa1/0x1b0 + __mlxsw_sp_inetaddr_lag_event+0xcc/0x130 + __mlxsw_sp_inetaddr_event+0xf5/0x3c0 + mlxsw_sp_router_netdevice_event+0x1015/0x1580 + notifier_call_chain+0xcc/0x150 + call_netdevice_notifiers_info+0x7e/0x100 + __netdev_upper_dev_unlink+0x10b/0x210 + netdev_upper_dev_unlink+0x79/0xa0 + vrf_del_slave+0x18/0x50 + do_set_master+0x146/0x7d0 + do_setlink.isra.0+0x9a0/0x2880 + rtnl_newlink+0x637/0xb20 + rtnetlink_rcv_msg+0x6fe/0xb90 + netlink_rcv_skb+0x123/0x380 + netlink_unicast+0x4a3/0x770 + netlink_sendmsg+0x75b/0xc90 + __sock_sendmsg+0xbe/0x160 + ____sys_sendmsg+0x5b2/0x7d0 + ___sys_sendmsg+0xfd/0x180 + __sys_sendmsg+0x124/0x1c0 + do_syscall_64+0xbb/0xfd0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[...] + +Allocated by task 109: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7b/0x90 + __kmalloc_noprof+0x2c1/0x790 + neigh_alloc+0x6af/0x8f0 + ___neigh_create+0x63/0xe90 + mlxsw_sp_nexthop_neigh_init+0x430/0x7e0 + mlxsw_sp_nexthop_type_init+0x212/0x960 + mlxsw_sp_nexthop6_group_info_init.constprop.0+0x81f/0x1280 + mlxsw_sp_nexthop6_group_get+0x392/0x6a0 + mlxsw_sp_fib6_entry_create+0x46a/0xfd0 + mlxsw_sp_router_fib6_replace+0x1ed/0x5f0 + mlxsw_sp_router_fib6_event_work+0x10a/0x2a0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Freed by task 154: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kmem_cache_free_bulk.part.0+0x1eb/0x5e0 + kvfree_rcu_bulk+0x1f2/0x260 + kfree_rcu_work+0x130/0x1b0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Last potentially related work creation: + kasan_save_stack+0x30/0x50 + kasan_record_aux_stack+0x8c/0xa0 + kvfree_call_rcu+0x93/0x5b0 + mlxsw_sp_router_neigh_event_work+0x67d/0x860 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Fixes: 6cf3c971dc84 ("mlxsw: spectrum_router: Add private neigh table") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/92d75e21d95d163a41b5cea67a15cd33f547cba6.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlxsw/spectrum_router.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index 55de90d5ae591..487ea65417b4a 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2137,6 +2137,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + if (!neigh_entry) + return NULL; + ++ neigh_hold(n); + neigh_entry->key.n = n; + neigh_entry->rif = rif; + INIT_LIST_HEAD(&neigh_entry->nexthop_list); +@@ -2146,6 +2147,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + + static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) + { ++ neigh_release(neigh_entry->key.n); + kfree(neigh_entry); + } + +@@ -3995,6 +3997,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + if (err) + goto err_neigh_entry_insert; + ++ neigh_release(old_n); ++ + read_lock_bh(&n->lock); + nud_state = n->nud_state; + dead = n->dead; +@@ -4003,14 +4007,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + + list_for_each_entry(nh, &neigh_entry->nexthop_list, + neigh_list_node) { +- neigh_release(old_n); +- neigh_clone(n); + __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + } + +- neigh_release(n); +- + return 0; + + err_neigh_entry_insert: +@@ -4098,6 +4098,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, + } + } + ++ /* Release the reference taken by neigh_lookup() / neigh_create() since ++ * neigh_entry already holds one. ++ */ ++ neigh_release(n); ++ + /* If that is the first nexthop connected to that neigh, add to + * nexthop_neighs_list + */ +@@ -4124,11 +4129,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) + { + struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; +- struct neighbour *n; + + if (!neigh_entry) + return; +- n = neigh_entry->key.n; + + __mlxsw_sp_nexthop_neigh_update(nh, true); + list_del(&nh->neigh_list_node); +@@ -4142,8 +4145,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + + if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) + mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); +- +- neigh_release(n); + } + + static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) +-- +2.51.0 + diff --git a/queue-5.15/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch b/queue-5.15/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch new file mode 100644 index 0000000000..b5bd98aa9c --- /dev/null +++ b/queue-5.15/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch @@ -0,0 +1,68 @@ +From 14295ef870e6b879c9cd87383a9ff821e8b81348 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Dec 2022 14:48:24 +0300 +Subject: net/ethtool/ioctl: remove if n_stats checks from + ethtool_get_phy_stats + +From: Daniil Tatianin + +[ Upstream commit fd4778581d61d8848b532f8cdc9b325138748437 ] + +Now that we always early return if we don't have any stats we can remove +these checks as they're no longer necessary. + +Signed-off-by: Daniil Tatianin +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 4b736385912ef..2ffd52d886cfc 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2085,28 +2085,24 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + + stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); +- if (!data) +- return -ENOMEM; ++ data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (!data) ++ return -ENOMEM; + +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(phydev, &stats, data); +- if (ret < 0) +- goto out; +- } else { +- ops->get_ethtool_phy_stats(dev, &stats, data); +- } ++ if (phydev && !ops->get_ethtool_phy_stats && ++ phy_ops && phy_ops->get_stats) { ++ ret = phy_ops->get_stats(phydev, &stats, data); ++ if (ret < 0) ++ goto out; + } else { +- data = NULL; ++ ops->get_ethtool_phy_stats(dev, &stats, data); + } + + ret = -EFAULT; + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) + goto out; + ret = 0; + +-- +2.51.0 + diff --git a/queue-5.15/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch b/queue-5.15/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch new file mode 100644 index 0000000000..644e1acef0 --- /dev/null +++ b/queue-5.15/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch @@ -0,0 +1,168 @@ +From b29a2eab7c9f4a9077988fdc7bb68e3f86b63d62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Dec 2022 14:48:25 +0300 +Subject: net/ethtool/ioctl: split ethtool_get_phy_stats into multiple helpers + +From: Daniil Tatianin + +[ Upstream commit 201ed315f9676809cd5b20a39206e964106d4f27 ] + +So that it's easier to follow and make sense of the branching and +various conditions. + +Stats retrieval has been split into two separate functions +ethtool_get_phy_stats_phydev & ethtool_get_phy_stats_ethtool. +The former attempts to retrieve the stats using phydev & phy_ops, while +the latter uses ethtool_ops. + +Actual n_stats validation & array allocation has been moved into a new +ethtool_vzalloc_stats_array helper. + +This also fixes a potential NULL dereference of +ops->get_ethtool_phy_stats where it was getting called in an else branch +unconditionally without making sure it was actually present. + +Found by Linux Verification Center (linuxtesting.org) with the SVACE +static analysis tool. + +Signed-off-by: Daniil Tatianin +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 102 ++++++++++++++++++++++++++++++-------------- + 1 file changed, 69 insertions(+), 33 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 2ffd52d886cfc..33b5c3d8f2f7f 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2056,23 +2056,8 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + return ret; + } + +-static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) ++static int ethtool_vzalloc_stats_array(int n_stats, u64 **data) + { +- const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; +- const struct ethtool_ops *ops = dev->ethtool_ops; +- struct phy_device *phydev = dev->phydev; +- struct ethtool_stats stats; +- u64 *data; +- int ret, n_stats; +- +- if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) +- return -EOPNOTSUPP; +- +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_sset_count) +- n_stats = phy_ops->get_sset_count(phydev); +- else +- n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); + if (n_stats < 0) + return n_stats; + if (n_stats > S32_MAX / sizeof(u64)) +@@ -2080,31 +2065,82 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (WARN_ON_ONCE(!n_stats)) + return -EOPNOTSUPP; + ++ *data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (!*data) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, ++ struct ethtool_stats *stats, ++ u64 **data) ++ { ++ const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; ++ int n_stats, ret; ++ ++ if (!phy_ops || !phy_ops->get_sset_count || !phy_ops->get_stats) ++ return -EOPNOTSUPP; ++ ++ n_stats = phy_ops->get_sset_count(phydev); ++ ++ ret = ethtool_vzalloc_stats_array(n_stats, data); ++ if (ret) ++ return ret; ++ ++ stats->n_stats = n_stats; ++ return phy_ops->get_stats(phydev, stats, *data); ++} ++ ++static int ethtool_get_phy_stats_ethtool(struct net_device *dev, ++ struct ethtool_stats *stats, ++ u64 **data) ++{ ++ const struct ethtool_ops *ops = dev->ethtool_ops; ++ int n_stats, ret; ++ ++ if (!ops || !ops->get_sset_count || ops->get_ethtool_phy_stats) ++ return -EOPNOTSUPP; ++ ++ n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ ++ ret = ethtool_vzalloc_stats_array(n_stats, data); ++ if (ret) ++ return ret; ++ ++ stats->n_stats = n_stats; ++ ops->get_ethtool_phy_stats(dev, stats, *data); ++ ++ return 0; ++} ++ ++static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) ++{ ++ struct phy_device *phydev = dev->phydev; ++ struct ethtool_stats stats; ++ u64 *data = NULL; ++ int ret = -EOPNOTSUPP; ++ + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (phydev) ++ ret = ethtool_get_phy_stats_phydev(phydev, &stats, &data); + +- data = vzalloc(array_size(n_stats, sizeof(u64))); +- if (!data) +- return -ENOMEM; ++ if (ret == -EOPNOTSUPP) ++ ret = ethtool_get_phy_stats_ethtool(dev, &stats, &data); + +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(phydev, &stats, data); +- if (ret < 0) +- goto out; +- } else { +- ops->get_ethtool_phy_stats(dev, &stats, data); +- } ++ if (ret) ++ goto out; + +- ret = -EFAULT; +- if (copy_to_user(useraddr, &stats, sizeof(stats))) ++ if (copy_to_user(useraddr, &stats, sizeof(stats))) { ++ ret = -EFAULT; + goto out; ++ } ++ + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) +- goto out; +- ret = 0; ++ if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ ret = -EFAULT; + + out: + vfree(data); +-- +2.51.0 + diff --git a/queue-5.15/net-hns3-add-vlan-id-validation-before-using.patch b/queue-5.15/net-hns3-add-vlan-id-validation-before-using.patch new file mode 100644 index 0000000000..a3cdcbf783 --- /dev/null +++ b/queue-5.15/net-hns3-add-vlan-id-validation-before-using.patch @@ -0,0 +1,46 @@ +From 9b7aaaedd59f3e52296222764f6dd3ed81777d90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:37 +0800 +Subject: net: hns3: add VLAN id validation before using + +From: Jian Shen + +[ Upstream commit 6ef935e65902bfed53980ad2754b06a284ea8ac1 ] + +Currently, the VLAN id may be used without validation when +receive a VLAN configuration mailbox from VF. The length of +vlan_del_fail_bmap is BITS_TO_LONGS(VLAN_N_VID). It may cause +out-of-bounds memory access once the VLAN id is bigger than +or equal to VLAN_N_VID. + +Therefore, VLAN id needs to be checked to ensure it is within +the range of VLAN_N_VID. + +Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 1dffd1532bd76..dd9d5df31905a 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -10682,6 +10682,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, + bool writen_to_tbl = false; + int ret = 0; + ++ if (vlan_id >= VLAN_N_VID) ++ return -EINVAL; ++ + /* When device is resetting or reset failed, firmware is unable to + * handle mailbox. Just record the vlan id, and remove it after + * reset finished. +-- +2.51.0 + diff --git a/queue-5.15/net-hns3-align-type-of-some-variables-with-their-pri.patch b/queue-5.15/net-hns3-align-type-of-some-variables-with-their-pri.patch new file mode 100644 index 0000000000..2c7a334ed6 --- /dev/null +++ b/queue-5.15/net-hns3-align-type-of-some-variables-with-their-pri.patch @@ -0,0 +1,78 @@ +From 1bfb8fe035686cc26684c186f63253b24b4920cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Dec 2021 17:20:52 +0800 +Subject: net: hns3: Align type of some variables with their print type + +From: Hao Chen + +[ Upstream commit 0cc25c6a14efd709f2cfcde345e3d5c6aa20f80e ] + +The c language has a set of implicit type conversions, when +two variables perform bitwise or arithmetic operations. + +For example, variable A (type u16/u8) -1, its output is int type variable. +u16/u8 will convert to int type implicitly before it does arithmetic +operations. So, change 1 to unsigned type. + +Signed-off-by: Hao Chen +Signed-off-by: Guangbin Huang +Signed-off-by: David S. Miller +Stable-dep-of: d180c11aa8a6 ("net: hns3: using the num_tqps to check whether tqp_index is out of range when vf get ring info from mbx") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 2 +- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++-- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +index 63665e8a7c718..016cd7cf11931 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +@@ -99,7 +99,7 @@ static void hclge_dbg_fill_content(char *content, u16 len, + static char *hclge_dbg_get_func_id_str(char *buf, u8 id) + { + if (id) +- sprintf(buf, "vf%u", id - 1); ++ sprintf(buf, "vf%u", id - 1U); + else + sprintf(buf, "pf"); + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 492a754f84a94..1dffd1532bd76 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -6692,7 +6692,7 @@ static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie, + if (vf > hdev->num_req_vfs) { + dev_err(&hdev->pdev->dev, + "Error: vf id (%u) should be less than %u\n", +- vf - 1, hdev->num_req_vfs); ++ vf - 1U, hdev->num_req_vfs); + return -EINVAL; + } + +@@ -6702,7 +6702,7 @@ static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie, + if (ring >= tqps) { + dev_err(&hdev->pdev->dev, + "Error: queue id (%u) > max tqp num (%u)\n", +- ring, tqps - 1); ++ ring, tqps - 1U); + return -EINVAL; + } + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index e2fe41d3972fb..e2cd0eb124bac 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -190,7 +190,7 @@ static int hclge_get_ring_chain_from_mbx( + if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { + dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", + req->msg.param[i].tqp_index, +- vport->nic.kinfo.rss_size - 1); ++ vport->nic.kinfo.rss_size - 1U); + return -EINVAL; + } + } +-- +2.51.0 + diff --git a/queue-5.15/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch b/queue-5.15/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch new file mode 100644 index 0000000000..b33afa0a41 --- /dev/null +++ b/queue-5.15/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch @@ -0,0 +1,52 @@ +From 4d5856ca9e581bb5a1806520c17fdc4a30a98e8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:35 +0800 +Subject: net: hns3: using the num_tqps in the vf driver to apply for resources + +From: Jian Shen + +[ Upstream commit c2a16269742e176fccdd0ef9c016a233491a49ad ] + +Currently, hdev->htqp is allocated using hdev->num_tqps, and kinfo->tqp +is allocated using kinfo->num_tqps. However, kinfo->num_tqps is set to +min(new_tqps, hdev->num_tqps); Therefore, kinfo->num_tqps may be smaller +than hdev->num_tqps, which causes some hdev->htqp[i] to remain +uninitialized in hclgevf_knic_setup(). + +Thus, this patch allocates hdev->htqp and kinfo->tqp using hdev->num_tqps, +ensuring that the lengths of hdev->htqp and kinfo->tqp are consistent +and that all elements are properly initialized. + +Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-2-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 94e615177ff14..0f3c91afba02b 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -458,12 +458,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) + new_tqps = kinfo->rss_size * num_tc; + kinfo->num_tqps = min(new_tqps, hdev->num_tqps); + +- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, ++ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, + sizeof(struct hnae3_queue *), GFP_KERNEL); + if (!kinfo->tqp) + return -ENOMEM; + +- for (i = 0; i < kinfo->num_tqps; i++) { ++ for (i = 0; i < hdev->num_tqps; i++) { + hdev->htqp[i].q.handle = &hdev->nic; + hdev->htqp[i].q.tqp_index = i; + kinfo->tqp[i] = &hdev->htqp[i].q; +-- +2.51.0 + diff --git a/queue-5.15/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch b/queue-5.15/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch new file mode 100644 index 0000000000..3d8e2f242b --- /dev/null +++ b/queue-5.15/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch @@ -0,0 +1,49 @@ +From e77f09da6500e71aa3b6c5d5078c7ff8877e42ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:36 +0800 +Subject: net: hns3: using the num_tqps to check whether tqp_index is out of + range when vf get ring info from mbx + +From: Jian Shen + +[ Upstream commit d180c11aa8a6fa735f9ac2c72c61364a9afc2ba7 ] + +Currently, rss_size = num_tqps / tc_num. If tc_num is 1, then num_tqps +equals rss_size. However, if the tc_num is greater than 1, then rss_size +will be less than num_tqps, causing the tqp_index check for subsequent TCs +using rss_size to always fail. + +This patch uses the num_tqps to check whether tqp_index is out of range, +instead of rss_size. + +Fixes: 326334aad024 ("net: hns3: add a check for tqp_index in hclge_get_ring_chain_from_mbx()") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-3-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index e2cd0eb124bac..f1823dd4473f7 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -187,10 +187,10 @@ static int hclge_get_ring_chain_from_mbx( + return -EINVAL; + + for (i = 0; i < ring_num; i++) { +- if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { ++ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { + dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", + req->msg.param[i].tqp_index, +- vport->nic.kinfo.rss_size - 1U); ++ vport->nic.kinfo.num_tqps - 1U); + return -EINVAL; + } + } +-- +2.51.0 + diff --git a/queue-5.15/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch b/queue-5.15/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch new file mode 100644 index 0000000000..f51799ebfa --- /dev/null +++ b/queue-5.15/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch @@ -0,0 +1,94 @@ +From 40ad300f327c9ed003c16bc279f19c9ec698bd8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Jan 2023 15:24:19 +0200 +Subject: net/mlx5: fw_tracer, Add support for unrecognized string + +From: Shay Drory + +[ Upstream commit f7133135235dbd11e7cb5fe62fe5d05ce5e82eeb ] + +In case FW is publishing a string which isn't found in the driver's +string DBs, keep the string as raw data. + +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: b35966042d20 ("net/mlx5: fw_tracer, Validate format string parameters") +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 25 +++++++++++++++++-- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index efa2e0a8fa1d1..d982b468dcc1d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -460,6 +460,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer, + + tracer_event->event_id = MLX5_GET(tracer_event, trace, event_id); + tracer_event->lost_event = MLX5_GET(tracer_event, trace, lost); ++ tracer_event->out = trace; + + switch (tracer_event->event_id) { + case TRACER_EVENT_TYPE_TIMESTAMP: +@@ -582,6 +583,26 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + mlx5_tracer_clean_message(str_frmt); + } + ++static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_event *tracer_event) ++{ ++ struct tracer_string_format *cur_string; ++ ++ cur_string = mlx5_tracer_message_insert(tracer, tracer_event); ++ if (!cur_string) ++ return -1; ++ ++ cur_string->event_id = tracer_event->event_id; ++ cur_string->timestamp = tracer_event->string_event.timestamp; ++ cur_string->lost = tracer_event->lost_event; ++ cur_string->string = "0x%08x%08x"; ++ cur_string->num_of_params = 2; ++ cur_string->params[0] = upper_32_bits(*tracer_event->out); ++ cur_string->params[1] = lower_32_bits(*tracer_event->out); ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++ return 0; ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -590,7 +611,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (tracer_event->string_event.tdsn == 0) { + cur_string = mlx5_tracer_get_string(tracer, tracer_event); + if (!cur_string) +- return -1; ++ return mlx5_tracer_handle_raw_string(tracer, tracer_event); + + cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); + cur_string->last_param_num = 0; +@@ -605,7 +626,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) { + pr_debug("%s Got string event for unknown string tmsn: %d\n", + __func__, tracer_event->string_event.tmsn); +- return -1; ++ return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 97252a85d65e6..568efb1e2bd24 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -158,6 +158,7 @@ struct tracer_event { + struct tracer_string_event string_event; + struct tracer_timestamp_event timestamp_event; + }; ++ u64 *out; + }; + + struct mlx5_ifc_tracer_event_bits { +-- +2.51.0 + diff --git a/queue-5.15/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch b/queue-5.15/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch new file mode 100644 index 0000000000..858b1b2888 --- /dev/null +++ b/queue-5.15/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch @@ -0,0 +1,84 @@ +From b305b28d62d1b3bf9ae55c001530bec995a27186 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:12 +0200 +Subject: net/mlx5: fw_tracer, Handle escaped percent properly + +From: Shay Drory + +[ Upstream commit c0289f67f7d6a0dfba0e92cfe661a5c70c8c6e92 ] + +The firmware tracer's format string validation and parameter counting +did not properly handle escaped percent signs (%%). This caused +fw_tracer to count more parameters when trace format strings contained +literal percent characters. + +To fix it, allow %% to pass string validation and skip %% sequences when +counting parameters since they represent literal percent signs rather +than format specifiers. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reported-by: Breno Leitao +Reviewed-by: Moshe Shemesh +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 6b49bda8bea2a..1779ff98b5892 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -364,11 +364,11 @@ static bool mlx5_is_valid_spec(const char *str) + while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') + str++; + +- /* Check if it's a valid integer/hex specifier: ++ /* Check if it's a valid integer/hex specifier or %%: + * Valid formats: %x, %d, %i, %u, etc. + */ + if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && +- *str != 'u' && *str != 'c') ++ *str != 'u' && *str != 'c' && *str != '%') + return false; + + return true; +@@ -386,7 +386,11 @@ static bool mlx5_tracer_validate_params(const char *str) + if (!mlx5_is_valid_spec(substr + 1)) + return false; + +- substr = strstr(substr + 1, PARAM_CHAR); ++ if (*(substr + 1) == '%') ++ substr = strstr(substr + 2, PARAM_CHAR); ++ else ++ substr = strstr(substr + 1, PARAM_CHAR); ++ + } + + return true; +@@ -463,11 +467,15 @@ static int mlx5_tracer_get_num_of_params(char *str) + substr = strstr(pstr, VAL_PARM); + } + +- /* count all the % characters */ ++ /* count all the % characters, but skip %% (escaped percent) */ + substr = strstr(str, PARAM_CHAR); + while (substr) { +- num_of_params += 1; +- str = substr + 1; ++ if (*(substr + 1) != '%') { ++ num_of_params += 1; ++ str = substr + 1; ++ } else { ++ str = substr + 2; ++ } + substr = strstr(str, PARAM_CHAR); + } + +-- +2.51.0 + diff --git a/queue-5.15/net-mlx5-fw_tracer-validate-format-string-parameters.patch b/queue-5.15/net-mlx5-fw_tracer-validate-format-string-parameters.patch new file mode 100644 index 0000000000..4d3d5b3f9f --- /dev/null +++ b/queue-5.15/net-mlx5-fw_tracer-validate-format-string-parameters.patch @@ -0,0 +1,195 @@ +From c3642412cb549a43918219348a6675a5769341d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:11 +0200 +Subject: net/mlx5: fw_tracer, Validate format string parameters + +From: Shay Drory + +[ Upstream commit b35966042d20b14e2d83330049f77deec5229749 ] + +Add validation for format string parameters in the firmware tracer to +prevent potential security vulnerabilities and crashes from malformed +format strings received from firmware. + +The firmware tracer receives format strings from the device firmware and +uses them to format trace messages. Without proper validation, bad +firmware could provide format strings with invalid format specifiers +(e.g., %s, %p, %n) that could lead to crashes, or other undefined +behavior. + +Add mlx5_tracer_validate_params() to validate that all format specifiers +in trace strings are limited to safe integer/hex formats (%x, %d, %i, +%u, %llx, %lx, etc.). Reject strings containing other format types that +could be used to access arbitrary memory or cause crashes. +Invalid format strings are added to the trace output for visibility with +"BAD_FORMAT: " prefix. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Reported-by: Breno Leitao +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 83 ++++++++++++++++--- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 74 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index d982b468dcc1d..6b49bda8bea2a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -33,6 +33,7 @@ + #include "lib/eq.h" + #include "fw_tracer.h" + #include "fw_tracer_tracepoint.h" ++#include + + static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) + { +@@ -354,6 +355,43 @@ static const char *VAL_PARM = "%llx"; + static const char *REPLACE_64_VAL_PARM = "%x%x"; + static const char *PARAM_CHAR = "%"; + ++static bool mlx5_is_valid_spec(const char *str) ++{ ++ /* Parse format specifiers to find the actual type. ++ * Structure: %[flags][width][.precision][length]type ++ * Skip flags, width, precision & length. ++ */ ++ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') ++ str++; ++ ++ /* Check if it's a valid integer/hex specifier: ++ * Valid formats: %x, %d, %i, %u, etc. ++ */ ++ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && ++ *str != 'u' && *str != 'c') ++ return false; ++ ++ return true; ++} ++ ++static bool mlx5_tracer_validate_params(const char *str) ++{ ++ const char *substr = str; ++ ++ if (!str) ++ return false; ++ ++ substr = strstr(substr, PARAM_CHAR); ++ while (substr) { ++ if (!mlx5_is_valid_spec(substr + 1)) ++ return false; ++ ++ substr = strstr(substr + 1, PARAM_CHAR); ++ } ++ ++ return true; ++} ++ + static int mlx5_tracer_message_hash(u32 message_id) + { + return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); +@@ -413,6 +451,10 @@ static int mlx5_tracer_get_num_of_params(char *str) + char *substr, *pstr = str; + int num_of_params = 0; + ++ /* Validate that all parameters are valid before processing */ ++ if (!mlx5_tracer_validate_params(str)) ++ return -EINVAL; ++ + /* replace %llx with %x%x */ + substr = strstr(pstr, VAL_PARM); + while (substr) { +@@ -564,14 +606,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + { + char tmp[512]; + +- snprintf(tmp, sizeof(tmp), str_frmt->string, +- str_frmt->params[0], +- str_frmt->params[1], +- str_frmt->params[2], +- str_frmt->params[3], +- str_frmt->params[4], +- str_frmt->params[5], +- str_frmt->params[6]); ++ if (str_frmt->invalid_string) ++ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string); ++ else ++ snprintf(tmp, sizeof(tmp), str_frmt->string, ++ str_frmt->params[0], ++ str_frmt->params[1], ++ str_frmt->params[2], ++ str_frmt->params[3], ++ str_frmt->params[4], ++ str_frmt->params[5], ++ str_frmt->params[6]); + + trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, + str_frmt->event_id, tmp); +@@ -603,6 +648,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, + return 0; + } + ++static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_string_format *cur_string) ++{ ++ cur_string->invalid_string = true; ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -613,12 +665,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + +- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); +- cur_string->last_param_num = 0; + cur_string->event_id = tracer_event->event_id; + cur_string->tmsn = tracer_event->string_event.tmsn; + cur_string->timestamp = tracer_event->string_event.timestamp; + cur_string->lost = tracer_event->lost_event; ++ cur_string->last_param_num = 0; ++ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s Invalid format string parameters\n", ++ __func__); ++ mlx5_tracer_handle_bad_format_string(tracer, cur_string); ++ return 0; ++ } + if (cur_string->num_of_params == 0) /* trace with no params */ + list_add_tail(&cur_string->list, &tracer->ready_strings_list); + } else { +@@ -628,6 +686,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + __func__, tracer_event->string_event.tmsn); + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s string parameter of invalid string, dumping\n", ++ __func__); ++ return 0; ++ } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { + pr_debug("%s Number of params exceeds the max (%d)\n", +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 568efb1e2bd24..603ef441f1b21 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -117,6 +117,7 @@ struct tracer_string_format { + struct list_head list; + u32 timestamp; + bool lost; ++ bool invalid_string; + }; + + enum mlx5_fw_tracer_ownership_state { +-- +2.51.0 + diff --git a/queue-5.15/net-openvswitch-fix-middle-attribute-validation-in-p.patch b/queue-5.15/net-openvswitch-fix-middle-attribute-validation-in-p.patch new file mode 100644 index 0000000000..2f62fcbd43 --- /dev/null +++ b/queue-5.15/net-openvswitch-fix-middle-attribute-validation-in-p.patch @@ -0,0 +1,112 @@ +From b41f0a0de980133f34a43f178e48a0baf2bfeac3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:53:32 +0100 +Subject: net: openvswitch: fix middle attribute validation in push_nsh() + action + +From: Ilya Maximets + +[ Upstream commit 5ace7ef87f059d68b5f50837ef3e8a1a4870c36e ] + +The push_nsh() action structure looks like this: + + OVS_ACTION_ATTR_PUSH_NSH(OVS_KEY_ATTR_NSH(OVS_NSH_KEY_ATTR_BASE,...)) + +The outermost OVS_ACTION_ATTR_PUSH_NSH attribute is OK'ed by the +nla_for_each_nested() inside __ovs_nla_copy_actions(). The innermost +OVS_NSH_KEY_ATTR_BASE/MD1/MD2 are OK'ed by the nla_for_each_nested() +inside nsh_key_put_from_nlattr(). But nothing checks if the attribute +in the middle is OK. We don't even check that this attribute is the +OVS_KEY_ATTR_NSH. We just do a double unwrap with a pair of nla_data() +calls - first time directly while calling validate_push_nsh() and the +second time as part of the nla_for_each_nested() macro, which isn't +safe, potentially causing invalid memory access if the size of this +attribute is incorrect. The failure may not be noticed during +validation due to larger netlink buffer, but cause trouble later during +action execution where the buffer is allocated exactly to the size: + + BUG: KASAN: slab-out-of-bounds in nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + Read of size 184 at addr ffff88816459a634 by task a.out/22624 + + CPU: 8 UID: 0 PID: 22624 6.18.0-rc7+ #115 PREEMPT(voluntary) + Call Trace: + + dump_stack_lvl+0x51/0x70 + print_address_description.constprop.0+0x2c/0x390 + kasan_report+0xdd/0x110 + kasan_check_range+0x35/0x1b0 + __asan_memcpy+0x20/0x60 + nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + push_nsh+0x82/0x120 [openvswitch] + do_execute_actions+0x1405/0x2840 [openvswitch] + ovs_execute_actions+0xd5/0x3b0 [openvswitch] + ovs_packet_cmd_execute+0x949/0xdb0 [openvswitch] + genl_family_rcv_msg_doit+0x1d6/0x2b0 + genl_family_rcv_msg+0x336/0x580 + genl_rcv_msg+0x9f/0x130 + netlink_rcv_skb+0x11f/0x370 + genl_rcv+0x24/0x40 + netlink_unicast+0x73e/0xaa0 + netlink_sendmsg+0x744/0xbf0 + __sys_sendto+0x3d6/0x450 + do_syscall_64+0x79/0x2c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + +Let's add some checks that the attribute is properly sized and it's +the only one attribute inside the action. Technically, there is no +real reason for OVS_KEY_ATTR_NSH to be there, as we know that we're +pushing an NSH header already, it just creates extra nesting, but +that's how uAPI works today. So, keeping as it is. + +Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") +Reported-by: Junvy Yang +Signed-off-by: Ilya Maximets +Acked-by: Eelco Chaudron echaudro@redhat.com +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20251204105334.900379-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 7c2692f897f99..a7a9e4df3f600 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2757,13 +2757,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, + return err; + } + +-static bool validate_push_nsh(const struct nlattr *attr, bool log) ++static bool validate_push_nsh(const struct nlattr *a, bool log) + { ++ struct nlattr *nsh_key = nla_data(a); + struct sw_flow_match match; + struct sw_flow_key key; + ++ /* There must be one and only one NSH header. */ ++ if (!nla_ok(nsh_key, nla_len(a)) || ++ nla_total_size(nla_len(nsh_key)) != nla_len(a) || ++ nla_type(nsh_key) != OVS_KEY_ATTR_NSH) ++ return false; ++ + ovs_match_init(&match, &key, true, NULL); +- return !nsh_key_put_from_nlattr(attr, &match, false, true, log); ++ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log); + } + + /* Return false if there are any non-masked bits set. +@@ -3317,7 +3324,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, + return -EINVAL; + } + mac_proto = MAC_PROTO_NONE; +- if (!validate_push_nsh(nla_data(a), log)) ++ if (!validate_push_nsh(a, log)) + return -EINVAL; + break; + +-- +2.51.0 + diff --git a/queue-5.15/net-sched-ets-always-remove-class-from-active-list-b.patch b/queue-5.15/net-sched-ets-always-remove-class-from-active-list-b.patch new file mode 100644 index 0000000000..6a616e983a --- /dev/null +++ b/queue-5.15/net-sched-ets-always-remove-class-from-active-list-b.patch @@ -0,0 +1,232 @@ +From 3afb391aa11b62ab453221daa5e4fa7e8f9ebaa3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: net/sched: ets: Always remove class from active list before deleting + in ets_qdisc_change + +From: Jamal Hadi Salim + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index d95d127975254..bcd91ffe9bc6a 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -665,7 +665,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.51.0 + diff --git a/queue-5.15/net-sched-ets-remove-drr-class-from-the-active-list-.patch b/queue-5.15/net-sched-ets-remove-drr-class-from-the-active-list-.patch new file mode 100644 index 0000000000..dade0c4aae --- /dev/null +++ b/queue-5.15/net-sched-ets-remove-drr-class-from-the-active-list-.patch @@ -0,0 +1,88 @@ +From 69192aab06414b1c096310bb5038b3493e4f20c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:01:24 -0300 +Subject: net/sched: ets: Remove drr class from the active list if it changes + to strict + +From: Victor Nogueira + +[ Upstream commit b1e125ae425aba9b45252e933ca8df52a843ec70 ] + +Whenever a user issues an ets qdisc change command, transforming a +drr class into a strict one, the ets code isn't checking whether that +class was in the active list and removing it. This means that, if a +user changes a strict class (which was in the active list) back to a drr +one, that class will be added twice to the active list [1]. + +Doing so with the following commands: + +tc qdisc add dev lo root handle 1: ets bands 2 strict 1 +tc qdisc add dev lo parent 1:2 handle 20: \ + tbf rate 8bit burst 100b latency 1s +tc filter add dev lo parent 1: basic classid 1:2 +ping -c1 -W0.01 -s 56 127.0.0.1 +tc qdisc change dev lo root handle 1: ets bands 2 strict 2 +tc qdisc change dev lo root handle 1: ets bands 2 strict 1 +ping -c1 -W0.01 -s 56 127.0.0.1 + +Will trigger the following splat with list debug turned on: + +[ 59.279014][ T365] ------------[ cut here ]------------ +[ 59.279452][ T365] list_add double add: new=ffff88801d60e350, prev=ffff88801d60e350, next=ffff88801d60e2c0. +[ 59.280153][ T365] WARNING: CPU: 3 PID: 365 at lib/list_debug.c:35 __list_add_valid_or_report+0x17f/0x220 +[ 59.280860][ T365] Modules linked in: +[ 59.281165][ T365] CPU: 3 UID: 0 PID: 365 Comm: tc Not tainted 6.18.0-rc7-00105-g7e9f13163c13-dirty #239 PREEMPT(voluntary) +[ 59.281977][ T365] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 59.282391][ T365] RIP: 0010:__list_add_valid_or_report+0x17f/0x220 +[ 59.282842][ T365] Code: 89 c6 e8 d4 b7 0d ff 90 0f 0b 90 90 31 c0 e9 31 ff ff ff 90 48 c7 c7 e0 a0 22 9f 48 89 f2 48 89 c1 4c 89 c6 e8 b2 b7 0d ff 90 <0f> 0b 90 90 31 c0 e9 0f ff ff ff 48 89 f7 48 89 44 24 10 4c 89 44 +... +[ 59.288812][ T365] Call Trace: +[ 59.289056][ T365] +[ 59.289224][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.289546][ T365] ets_qdisc_change+0xd2b/0x1e80 +[ 59.289891][ T365] ? __lock_acquire+0x7e7/0x1be0 +[ 59.290223][ T365] ? __pfx_ets_qdisc_change+0x10/0x10 +[ 59.290546][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.290898][ T365] ? __mutex_trylock_common+0xda/0x240 +[ 59.291228][ T365] ? __pfx___mutex_trylock_common+0x10/0x10 +[ 59.291655][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.291993][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.292313][ T365] ? trace_contention_end+0xc8/0x110 +[ 59.292656][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293022][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293351][ T365] tc_modify_qdisc+0x63a/0x1cf0 + +Fix this by always checking and removing an ets class from the active list +when changing it to strict. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/net/sched/sch_ets.c?id=ce052b9402e461a9aded599f5b47e76bc727f7de#n663 + +Fixes: cd9b50adc6bb9 ("net/sched: ets: fix crash when flipping from 'strict' to 'quantum'") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Reviewed-by: Petr Machata +Link: https://patch.msgid.link/20251208190125.1868423-1-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index bcd91ffe9bc6a..ce3d41a4d4f6a 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -677,6 +677,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nstrict; i < nstrict; i++) { ++ if (cl_is_active(&q->classes[i])) ++ list_del_init(&q->classes[i].alist); ++ } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + +-- +2.51.0 + diff --git a/queue-5.15/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch b/queue-5.15/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch new file mode 100644 index 0000000000..86c43ea537 --- /dev/null +++ b/queue-5.15/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch @@ -0,0 +1,90 @@ +From ec370ef854c0e4e8d5f611613e3ffbd3c3301405 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 12:58:01 +0100 +Subject: netfilter: nf_conncount: fix leaked ct in error paths + +From: Fernando Fernandez Mancera + +[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ] + +There are some situations where ct might be leaked as error paths are +skipping the refcounted check and return immediately. In order to solve +it make sure that the check is always called. + +Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conncount.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index 97b631a81484d..c00b8e522c5a7 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net, + struct nf_conn *found_ct; + unsigned int collect = 0; + bool refcounted = false; ++ int err = 0; + + if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- if (refcounted) +- nf_ct_put(ct); +- return -EEXIST; ++ err = -EEXIST; ++ goto out_put; + } + + if ((u32)jiffies == list->last_gc) +@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net, + } + + add_new_node: +- if (WARN_ON_ONCE(list->count > INT_MAX)) +- return -EOVERFLOW; ++ if (WARN_ON_ONCE(list->count > INT_MAX)) { ++ err = -EOVERFLOW; ++ goto out_put; ++ } + + conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); +- if (conn == NULL) +- return -ENOMEM; ++ if (conn == NULL) { ++ err = -ENOMEM; ++ goto out_put; ++ } + + conn->tuple = tuple; + conn->zone = *zone; +@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net, + out_put: + if (refcounted) + nf_ct_put(ct); +- return 0; ++ return err; + } + + int nf_conncount_add_skb(struct net *net, +@@ -446,11 +450,10 @@ insert_tree(struct net *net, + + rb_link_node_rcu(&rbconn->node, parent, rbnode); + rb_insert_color(&rbconn->node, root); +- +- if (refcounted) +- nf_ct_put(ct); + } + out_unlock: ++ if (refcounted) ++ nf_ct_put(ct); + spin_unlock_bh(&nf_conncount_locks[hash]); + return count; + } +-- +2.51.0 + diff --git a/queue-5.15/netrom-fix-memory-leak-in-nr_sendmsg.patch b/queue-5.15/netrom-fix-memory-leak-in-nr_sendmsg.patch new file mode 100644 index 0000000000..171f7796fe --- /dev/null +++ b/queue-5.15/netrom-fix-memory-leak-in-nr_sendmsg.patch @@ -0,0 +1,74 @@ +From af72b1c3f0379695d49363d764ddaaf557935e40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 12:13:15 +0800 +Subject: netrom: Fix memory leak in nr_sendmsg() + +From: Wang Liang + +[ Upstream commit 613d12dd794e078be8ff3cf6b62a6b9acf7f4619 ] + +syzbot reported a memory leak [1]. + +When function sock_alloc_send_skb() return NULL in nr_output(), the +original skb is not freed, which was allocated in nr_sendmsg(). Fix this +by freeing it before return. + +[1] +BUG: memory leak +unreferenced object 0xffff888129f35500 (size 240): + comm "syz.0.17", pid 6119, jiffies 4294944652 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 10 52 28 81 88 ff ff ..........R(.... + backtrace (crc 1456a3e4): + kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline] + slab_post_alloc_hook mm/slub.c:4983 [inline] + slab_alloc_node mm/slub.c:5288 [inline] + kmem_cache_alloc_node_noprof+0x36f/0x5e0 mm/slub.c:5340 + __alloc_skb+0x203/0x240 net/core/skbuff.c:660 + alloc_skb include/linux/skbuff.h:1383 [inline] + alloc_skb_with_frags+0x69/0x3f0 net/core/skbuff.c:6671 + sock_alloc_send_pskb+0x379/0x3e0 net/core/sock.c:2965 + sock_alloc_send_skb include/net/sock.h:1859 [inline] + nr_sendmsg+0x287/0x450 net/netrom/af_netrom.c:1105 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg net/socket.c:742 [inline] + sock_write_iter+0x293/0x2a0 net/socket.c:1195 + new_sync_write fs/read_write.c:593 [inline] + vfs_write+0x45d/0x710 fs/read_write.c:686 + ksys_write+0x143/0x170 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xa4/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7abc36bbbb6d7d40b58 +Tested-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20251129041315.1550766-1-wangliang74@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_out.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 5e531394a724b..2b3cbceb0b52d 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) + frontlen = skb_headroom(skb); + + while (skb->len > 0) { +- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) ++ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) { ++ kfree_skb(skb); + return; ++ } + + skb_reserve(skbn, frontlen); + +-- +2.51.0 + diff --git a/queue-5.15/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch b/queue-5.15/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch new file mode 100644 index 0000000000..17671f6ce3 --- /dev/null +++ b/queue-5.15/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch @@ -0,0 +1,37 @@ +From a9efa6b146a810c6de7d68c69defa2783cad7c8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 09:56:39 +0300 +Subject: nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() + +From: Dan Carpenter + +[ Upstream commit 885bebac9909994050bbbeed0829c727e42bd1b7 ] + +Set the error code if "transferred != sizeof(cmd)" instead of +returning success. + +Fixes: dbafc28955fa ("NFC: pn533: don't send USB data off of the stack") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aTfIJ9tZPmeUF4W1@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c +index 47d423cc26081..11d3c4045c1e1 100644 +--- a/drivers/nfc/pn533/usb.c ++++ b/drivers/nfc/pn533/usb.c +@@ -407,7 +407,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) + if (rc || (transferred != sizeof(cmd))) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); +- return rc; ++ return rc ?: -EINVAL; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); +-- +2.51.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 2792f2f5e6..46bed951bb 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -220,3 +220,26 @@ hfsplus-verify-inode-mode-when-loading-from-disk.patch hfsplus-fix-volume-corruption-issue-for-generic-073.patch btrfs-scrub-always-update-btrfs_scrub_progress-last_.patch bluetooth-btusb-add-new-vid-pid-13d3-3533-for-rtl882.patch +netrom-fix-memory-leak-in-nr_sendmsg.patch +net-sched-ets-always-remove-class-from-active-list-b.patch +ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch +mlxsw-spectrum_router-fix-neighbour-use-after-free.patch +mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch +net-openvswitch-fix-middle-attribute-validation-in-p.patch +broadcom-b44-prevent-uninitialized-value-usage.patch +netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch +ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch +caif-fix-integer-underflow-in-cffrml_receive.patch +net-sched-ets-remove-drr-class-from-the-active-list-.patch +nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch +ethtool-use-phydev-variable.patch +net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch +net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch +ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch +net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch +net-mlx5-fw_tracer-validate-format-string-parameters.patch +net-mlx5-fw_tracer-handle-escaped-percent-properly.patch +net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch +net-hns3-align-type-of-some-variables-with-their-pri.patch +net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch +net-hns3-add-vlan-id-validation-before-using.patch diff --git a/queue-6.1/broadcom-b44-prevent-uninitialized-value-usage.patch b/queue-6.1/broadcom-b44-prevent-uninitialized-value-usage.patch new file mode 100644 index 0000000000..d45118116d --- /dev/null +++ b/queue-6.1/broadcom-b44-prevent-uninitialized-value-usage.patch @@ -0,0 +1,45 @@ +From 99233debd4425b71f2e284d2c7f77ed41cd870d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 18:58:16 +0300 +Subject: broadcom: b44: prevent uninitialized value usage + +From: Alexey Simakov + +[ Upstream commit 50b3db3e11864cb4e18ff099cfb38e11e7f87a68 ] + +On execution path with raised B44_FLAG_EXTERNAL_PHY, b44_readphy() +leaves bmcr value uninitialized and it is used later in the code. + +Add check of this flag at the beginning of the b44_nway_reset() and +exit early of the function with restarting autonegotiation if an +external PHY is used. + +Fixes: 753f492093da ("[B44]: port to native ssb support") +Reviewed-by: Jonas Gorski +Reviewed-by: Andrew Lunn +Signed-off-by: Alexey Simakov +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20251205155815.4348-1-bigalex934@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/b44.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c +index 5b6209f5a8017..b3e3e869c4379 100644 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -1811,6 +1811,9 @@ static int b44_nway_reset(struct net_device *dev) + u32 bmcr; + int r; + ++ if (bp->flags & B44_FLAG_EXTERNAL_PHY) ++ return phy_ethtool_nway_reset(dev); ++ + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); +-- +2.51.0 + diff --git a/queue-6.1/caif-fix-integer-underflow-in-cffrml_receive.patch b/queue-6.1/caif-fix-integer-underflow-in-cffrml_receive.patch new file mode 100644 index 0000000000..be50c7190e --- /dev/null +++ b/queue-6.1/caif-fix-integer-underflow-in-cffrml_receive.patch @@ -0,0 +1,58 @@ +From d610ea84c5db5a8fa9c95770d41e328c37a381c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 21:30:47 +0800 +Subject: caif: fix integer underflow in cffrml_receive() + +From: Junrui Luo + +[ Upstream commit 8a11ff0948b5ad09b71896b7ccc850625f9878d1 ] + +The cffrml_receive() function extracts a length field from the packet +header and, when FCS is disabled, subtracts 2 from this length without +validating that len >= 2. + +If an attacker sends a malicious packet with a length field of 0 or 1 +to an interface with FCS disabled, the subtraction causes an integer +underflow. + +This can lead to memory exhaustion and kernel instability, potential +information disclosure if padding contains uninitialized kernel memory. + +Fix this by validating that len >= 2 before performing the subtraction. + +Reported-by: Yuhao Jiang +Reported-by: Junrui Luo +Fixes: b482cd2053e3 ("net-caif: add CAIF core protocol stack") +Signed-off-by: Junrui Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/SYBPR01MB7881511122BAFEA8212A1608AFA6A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/caif/cffrml.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c +index 6651a8dc62e04..d4d63586053ad 100644 +--- a/net/caif/cffrml.c ++++ b/net/caif/cffrml.c +@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) + len = le16_to_cpu(tmp); + + /* Subtract for FCS on length if FCS is not used. */ +- if (!this->dofcs) ++ if (!this->dofcs) { ++ if (len < 2) { ++ ++cffrml_rcv_error; ++ pr_err("Invalid frame length (%d)\n", len); ++ cfpkt_destroy(pkt); ++ return -EPROTO; ++ } + len -= 2; ++ } + + if (cfpkt_setlen(pkt, len) < 0) { + ++cffrml_rcv_error; +-- +2.51.0 + diff --git a/queue-6.1/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch b/queue-6.1/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch new file mode 100644 index 0000000000..213e6628f2 --- /dev/null +++ b/queue-6.1/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch @@ -0,0 +1,159 @@ +From 887aaaabe2fbab1d5e0d5ac6b201af539510975b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 14:19:01 +0200 +Subject: ethtool: Avoid overflowing userspace buffer on stats query + +From: Gal Pressman + +[ Upstream commit 7b07be1ff1cb6c49869910518650e8d0abc7d25f ] + +The ethtool -S command operates across three ioctl calls: +ETHTOOL_GSSET_INFO for the size, ETHTOOL_GSTRINGS for the names, and +ETHTOOL_GSTATS for the values. + +If the number of stats changes between these calls (e.g., due to device +reconfiguration), userspace's buffer allocation will be incorrect, +potentially leading to buffer overflow. + +Drivers are generally expected to maintain stable stat counts, but some +drivers (e.g., mlx5, bnx2x, bna, ksz884x) use dynamic counters, making +this scenario possible. + +Some drivers try to handle this internally: +- bnad_get_ethtool_stats() returns early in case stats.n_stats is not + equal to the driver's stats count. +- micrel/ksz884x also makes sure not to write anything beyond + stats.n_stats and overflow the buffer. + +However, both use stats.n_stats which is already assigned with the value +returned from get_sset_count(), hence won't solve the issue described +here. + +Change ethtool_get_strings(), ethtool_get_stats(), +ethtool_get_phy_stats() to not return anything in case of a mismatch +between userspace's size and get_sset_size(), to prevent buffer +overflow. +The returned n_stats value will be equal to zero, to reflect that +nothing has been returned. + +This could result in one of two cases when using upstream ethtool, +depending on when the size change is detected: +1. When detected in ethtool_get_strings(): + # ethtool -S eth2 + no stats available + +2. When detected in get stats, all stats will be reported as zero. + +Both cases are presumably transient, and a subsequent ethtool call +should succeed. + +Other than the overflow avoidance, these two cases are very evident (no +output/cleared stats), which is arguably better than presenting +incorrect/shifted stats. +I also considered returning an error instead of a "silent" response, but +that seems more destructive towards userspace apps. + +Notes: +- This patch does not claim to fix the inherent race, it only makes sure + that we do not overflow the userspace buffer, and makes for a more + predictable behavior. + +- RTNL lock is held during each ioctl, the race window exists between + the separate ioctl calls when the lock is released. + +- Userspace ethtool always fills stats.n_stats, but it is likely that + these stats ioctls are implemented in other userspace applications + which might not fill it. The added code checks that it's not zero, + to prevent any regressions. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Dragos Tatulea +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Link: https://patch.msgid.link/20251208121901.3203692-1-gal@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 208a40ae4ccbb..0e45e7fd68bf2 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1938,7 +1938,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + return -ENOMEM; + WARN_ON_ONCE(!ret); + +- gstrings.len = ret; ++ if (gstrings.len && gstrings.len != ret) ++ gstrings.len = 0; ++ else ++ gstrings.len = ret; + + if (gstrings.len) { + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); +@@ -2053,10 +2056,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (stats.n_stats && stats.n_stats != n_stats) ++ stats.n_stats = 0; ++ else ++ stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (stats.n_stats) { ++ data = vzalloc(array_size(stats.n_stats, sizeof(u64))); + if (!data) + return -ENOMEM; + ops->get_ethtool_stats(dev, &stats, data); +@@ -2068,7 +2074,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + goto out; + ret = 0; + +@@ -2104,6 +2112,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, + return -EOPNOTSUPP; + + n_stats = phy_ops->get_sset_count(phydev); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2124,6 +2136,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev, + return -EOPNOTSUPP; + + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2160,7 +2176,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + } + + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + ret = -EFAULT; + + out: +-- +2.51.0 + diff --git a/queue-6.1/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch b/queue-6.1/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch new file mode 100644 index 0000000000..26a4c4d351 --- /dev/null +++ b/queue-6.1/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch @@ -0,0 +1,48 @@ +From 8592d19a7794a27cf1ec702fea179f21c6632071 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 13:39:03 +0300 +Subject: ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() + +From: Dmitry Skorodumov + +[ Upstream commit 0c57ff008a11f24f7f05fa760222692a00465fec ] + +Packets with pkt_type == PACKET_LOOPBACK are captured by +handle_frame() function, but they don't have L2 header. +We should not process them in handle_mode_l2(). + +This doesn't affect old L2 functionality, since handling +was anyway incorrect. + +Handle them the same way as in br_handle_frame(): +just pass the skb. + +To observe invalid behaviour, just start "ping -b" on bcast address +of port-interface. + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Signed-off-by: Dmitry Skorodumov +Link: https://patch.msgid.link/20251202103906.4087675-1-skorodumov.dmitry@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index eea81a7334052..a8017424ab538 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -738,6 +738,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + ++ if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) ++ return RX_HANDLER_PASS; ++ + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.1/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch b/queue-6.1/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch new file mode 100644 index 0000000000..3249eb66f2 --- /dev/null +++ b/queue-6.1/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch @@ -0,0 +1,80 @@ +From 52ecb9bf59aabd290843dc6279f964c7fc210b8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 16:52:13 +0800 +Subject: ipvs: fix ipv4 null-ptr-deref in route error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Slavin Liu + +[ Upstream commit ad891bb3d079a46a821bf2b8867854645191bab0 ] + +The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure() +without ensuring skb->dev is set, leading to a NULL pointer dereference +in fib_compute_spec_dst() when ipv4_link_failure() attempts to send +ICMP destination unreachable messages. + +The issue emerged after commit ed0de45a1008 ("ipv4: recompile ip options +in ipv4_link_failure") started calling __ip_options_compile() from +ipv4_link_failure(). This code path eventually calls fib_compute_spec_dst() +which dereferences skb->dev. An attempt was made to fix the NULL skb->dev +dereference in commit 0113d9c9d1cc ("ipv4: fix null-deref in +ipv4_link_failure"), but it only addressed the immediate dev_net(skb->dev) +dereference by using a fallback device. The fix was incomplete because +fib_compute_spec_dst() later in the call chain still accesses skb->dev +directly, which remains NULL when IPVS calls dst_link_failure(). + +The crash occurs when: +1. IPVS processes a packet in NAT mode with a misconfigured destination +2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route +3. The error path calls dst_link_failure(skb) with skb->dev == NULL +4. ipv4_link_failure() → ipv4_send_dest_unreach() → + __ip_options_compile() → fib_compute_spec_dst() +5. fib_compute_spec_dst() dereferences NULL skb->dev + +Apply the same fix used for IPv6 in commit 326bf17ea5d4 ("ipvs: fix +ipv6 route unreach panic"): set skb->dev from skb_dst(skb)->dev before +calling dst_link_failure(). + +KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f] +CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2 +RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233 +RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285 +Call Trace: + + spec_dst_fill net/ipv4/ip_options.c:232 + spec_dst_fill net/ipv4/ip_options.c:229 + __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330 + ipv4_send_dest_unreach net/ipv4/route.c:1252 + ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265 + dst_link_failure include/net/dst.h:437 + __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412 + ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764 + +Fixes: ed0de45a1008 ("ipv4: recompile ip options in ipv4_link_failure") +Signed-off-by: Slavin Liu +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/ipvs/ip_vs_xmit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index e1437c72ca6e6..038f0bbbc9f6d 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -409,6 +409,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + return -1; + + err_unreach: ++ if (!skb->dev) ++ skb->dev = skb_dst(skb)->dev; ++ + dst_link_failure(skb); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.1/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch b/queue-6.1/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch new file mode 100644 index 0000000000..7b8310eb0a --- /dev/null +++ b/queue-6.1/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch @@ -0,0 +1,96 @@ +From b2c769344c43bcbe867197ea7ec0c0f052ad5b85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:13 +0100 +Subject: mlxsw: spectrum_mr: Fix use-after-free when updating multicast route + stats + +From: Ido Schimmel + +[ Upstream commit 8ac1dacec458f55f871f7153242ed6ab60373b90 ] + +Cited commit added a dedicated mutex (instead of RTNL) to protect the +multicast route list, so that it will not change while the driver +periodically traverses it in order to update the kernel about multicast +route stats that were queried from the device. + +One instance of list entry deletion (during route replace) was missed +and it can result in a use-after-free [1]. + +Fix by acquiring the mutex before deleting the entry from the list and +releasing it afterwards. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] +Read of size 8 at addr ffff8881523c2fa8 by task kworker/2:5/22043 + +CPU: 2 UID: 0 PID: 22043 Comm: kworker/2:5 Not tainted 6.18.0-rc1-custom-g1a3d6d7cd014 #1 PREEMPT(full) +Hardware name: Mellanox Technologies Ltd. MSN2010/SA002610, BIOS 5.6.5 08/24/2017 +Workqueue: mlxsw_core mlxsw_sp_mr_stats_update [mlxsw_spectrum] +Call Trace: + + dump_stack_lvl+0xba/0x110 + print_report+0x174/0x4f5 + kasan_report+0xdf/0x110 + mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + mlxsw_sp_mr_route_add+0xd8/0x4770 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x43/0x70 + kfree+0x14e/0x700 + mlxsw_sp_mr_route_add+0x2dea/0x4770 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:444 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Fixes: f38656d06725 ("mlxsw: spectrum_mr: Protect multicast route list with a lock") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/f996feecfd59fde297964bfc85040b6d83ec6089.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +index 1f6bc0c7e91dd..c39aca54a0d6b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table, + rhashtable_remove_fast(&mr_table->route_ht, + &mr_orig_route->ht_node, + mlxsw_sp_mr_route_ht_params); ++ mutex_lock(&mr_table->route_list_lock); + list_del(&mr_orig_route->node); ++ mutex_unlock(&mr_table->route_list_lock); + mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); + } + +-- +2.51.0 + diff --git a/queue-6.1/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch b/queue-6.1/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch new file mode 100644 index 0000000000..a3da38e650 --- /dev/null +++ b/queue-6.1/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch @@ -0,0 +1,199 @@ +From df2e2f852c60cefbddb3e744e0c4f45c851f461f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:12 +0100 +Subject: mlxsw: spectrum_router: Fix neighbour use-after-free + +From: Ido Schimmel + +[ Upstream commit 8b0e69763ef948fb872a7767df4be665d18f5fd4 ] + +We sometimes observe use-after-free when dereferencing a neighbour [1]. +The problem seems to be that the driver stores a pointer to the +neighbour, but without holding a reference on it. A reference is only +taken when the neighbour is used by a nexthop. + +Fix by simplifying the reference counting scheme. Always take a +reference when storing a neighbour pointer in a neighbour entry. Avoid +taking a referencing when the neighbour is used by a nexthop as the +neighbour entry associated with the nexthop already holds a reference. + +Tested by running the test that uncovered the problem over 300 times. +Without this patch the problem was reproduced after a handful of +iterations. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_neigh_entry_update+0x2d4/0x310 +Read of size 8 at addr ffff88817f8e3420 by task ip/3929 + +CPU: 3 UID: 0 PID: 3929 Comm: ip Not tainted 6.18.0-rc4-virtme-g36b21a067510 #3 PREEMPT(full) +Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 +Call Trace: + + dump_stack_lvl+0x6f/0xa0 + print_address_description.constprop.0+0x6e/0x300 + print_report+0xfc/0x1fb + kasan_report+0xe4/0x110 + mlxsw_sp_neigh_entry_update+0x2d4/0x310 + mlxsw_sp_router_rif_gone_sync+0x35f/0x510 + mlxsw_sp_rif_destroy+0x1ea/0x730 + mlxsw_sp_inetaddr_port_vlan_event+0xa1/0x1b0 + __mlxsw_sp_inetaddr_lag_event+0xcc/0x130 + __mlxsw_sp_inetaddr_event+0xf5/0x3c0 + mlxsw_sp_router_netdevice_event+0x1015/0x1580 + notifier_call_chain+0xcc/0x150 + call_netdevice_notifiers_info+0x7e/0x100 + __netdev_upper_dev_unlink+0x10b/0x210 + netdev_upper_dev_unlink+0x79/0xa0 + vrf_del_slave+0x18/0x50 + do_set_master+0x146/0x7d0 + do_setlink.isra.0+0x9a0/0x2880 + rtnl_newlink+0x637/0xb20 + rtnetlink_rcv_msg+0x6fe/0xb90 + netlink_rcv_skb+0x123/0x380 + netlink_unicast+0x4a3/0x770 + netlink_sendmsg+0x75b/0xc90 + __sock_sendmsg+0xbe/0x160 + ____sys_sendmsg+0x5b2/0x7d0 + ___sys_sendmsg+0xfd/0x180 + __sys_sendmsg+0x124/0x1c0 + do_syscall_64+0xbb/0xfd0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[...] + +Allocated by task 109: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7b/0x90 + __kmalloc_noprof+0x2c1/0x790 + neigh_alloc+0x6af/0x8f0 + ___neigh_create+0x63/0xe90 + mlxsw_sp_nexthop_neigh_init+0x430/0x7e0 + mlxsw_sp_nexthop_type_init+0x212/0x960 + mlxsw_sp_nexthop6_group_info_init.constprop.0+0x81f/0x1280 + mlxsw_sp_nexthop6_group_get+0x392/0x6a0 + mlxsw_sp_fib6_entry_create+0x46a/0xfd0 + mlxsw_sp_router_fib6_replace+0x1ed/0x5f0 + mlxsw_sp_router_fib6_event_work+0x10a/0x2a0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Freed by task 154: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kmem_cache_free_bulk.part.0+0x1eb/0x5e0 + kvfree_rcu_bulk+0x1f2/0x260 + kfree_rcu_work+0x130/0x1b0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Last potentially related work creation: + kasan_save_stack+0x30/0x50 + kasan_record_aux_stack+0x8c/0xa0 + kvfree_call_rcu+0x93/0x5b0 + mlxsw_sp_router_neigh_event_work+0x67d/0x860 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Fixes: 6cf3c971dc84 ("mlxsw: spectrum_router: Add private neigh table") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/92d75e21d95d163a41b5cea67a15cd33f547cba6.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlxsw/spectrum_router.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index a00dd0ee524e1..3fa790c5ef747 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2163,6 +2163,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + if (!neigh_entry) + return NULL; + ++ neigh_hold(n); + neigh_entry->key.n = n; + neigh_entry->rif = rif; + INIT_LIST_HEAD(&neigh_entry->nexthop_list); +@@ -2172,6 +2173,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + + static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) + { ++ neigh_release(neigh_entry->key.n); + kfree(neigh_entry); + } + +@@ -4027,6 +4029,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + if (err) + goto err_neigh_entry_insert; + ++ neigh_release(old_n); ++ + read_lock_bh(&n->lock); + nud_state = n->nud_state; + dead = n->dead; +@@ -4035,14 +4039,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + + list_for_each_entry(nh, &neigh_entry->nexthop_list, + neigh_list_node) { +- neigh_release(old_n); +- neigh_clone(n); + __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + } + +- neigh_release(n); +- + return 0; + + err_neigh_entry_insert: +@@ -4130,6 +4130,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, + } + } + ++ /* Release the reference taken by neigh_lookup() / neigh_create() since ++ * neigh_entry already holds one. ++ */ ++ neigh_release(n); ++ + /* If that is the first nexthop connected to that neigh, add to + * nexthop_neighs_list + */ +@@ -4156,11 +4161,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) + { + struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; +- struct neighbour *n; + + if (!neigh_entry) + return; +- n = neigh_entry->key.n; + + __mlxsw_sp_nexthop_neigh_update(nh, true); + list_del(&nh->neigh_list_node); +@@ -4174,8 +4177,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + + if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) + mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); +- +- neigh_release(n); + } + + static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) +-- +2.51.0 + diff --git a/queue-6.1/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch b/queue-6.1/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch new file mode 100644 index 0000000000..8793b2935a --- /dev/null +++ b/queue-6.1/net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch @@ -0,0 +1,68 @@ +From 6cdfffe30ec820ef348cddf2d72adc79c237fc52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Dec 2022 14:48:24 +0300 +Subject: net/ethtool/ioctl: remove if n_stats checks from + ethtool_get_phy_stats + +From: Daniil Tatianin + +[ Upstream commit fd4778581d61d8848b532f8cdc9b325138748437 ] + +Now that we always early return if we don't have any stats we can remove +these checks as they're no longer necessary. + +Signed-off-by: Daniil Tatianin +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 442c4c343e155..b85f055767035 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2106,28 +2106,24 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + + stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); +- if (!data) +- return -ENOMEM; ++ data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (!data) ++ return -ENOMEM; + +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(phydev, &stats, data); +- if (ret < 0) +- goto out; +- } else { +- ops->get_ethtool_phy_stats(dev, &stats, data); +- } ++ if (phydev && !ops->get_ethtool_phy_stats && ++ phy_ops && phy_ops->get_stats) { ++ ret = phy_ops->get_stats(phydev, &stats, data); ++ if (ret < 0) ++ goto out; + } else { +- data = NULL; ++ ops->get_ethtool_phy_stats(dev, &stats, data); + } + + ret = -EFAULT; + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) + goto out; + ret = 0; + +-- +2.51.0 + diff --git a/queue-6.1/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch b/queue-6.1/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch new file mode 100644 index 0000000000..7f558ac26f --- /dev/null +++ b/queue-6.1/net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch @@ -0,0 +1,168 @@ +From a2398aab1f3390a622df57828ac58bcd8b173d2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Dec 2022 14:48:25 +0300 +Subject: net/ethtool/ioctl: split ethtool_get_phy_stats into multiple helpers + +From: Daniil Tatianin + +[ Upstream commit 201ed315f9676809cd5b20a39206e964106d4f27 ] + +So that it's easier to follow and make sense of the branching and +various conditions. + +Stats retrieval has been split into two separate functions +ethtool_get_phy_stats_phydev & ethtool_get_phy_stats_ethtool. +The former attempts to retrieve the stats using phydev & phy_ops, while +the latter uses ethtool_ops. + +Actual n_stats validation & array allocation has been moved into a new +ethtool_vzalloc_stats_array helper. + +This also fixes a potential NULL dereference of +ops->get_ethtool_phy_stats where it was getting called in an else branch +unconditionally without making sure it was actually present. + +Found by Linux Verification Center (linuxtesting.org) with the SVACE +static analysis tool. + +Signed-off-by: Daniil Tatianin +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Stable-dep-of: 7b07be1ff1cb ("ethtool: Avoid overflowing userspace buffer on stats query") +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 102 ++++++++++++++++++++++++++++++-------------- + 1 file changed, 69 insertions(+), 33 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index b85f055767035..208a40ae4ccbb 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2077,23 +2077,8 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + return ret; + } + +-static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) ++static int ethtool_vzalloc_stats_array(int n_stats, u64 **data) + { +- const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; +- const struct ethtool_ops *ops = dev->ethtool_ops; +- struct phy_device *phydev = dev->phydev; +- struct ethtool_stats stats; +- u64 *data; +- int ret, n_stats; +- +- if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) +- return -EOPNOTSUPP; +- +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_sset_count) +- n_stats = phy_ops->get_sset_count(phydev); +- else +- n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); + if (n_stats < 0) + return n_stats; + if (n_stats > S32_MAX / sizeof(u64)) +@@ -2101,31 +2086,82 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + if (WARN_ON_ONCE(!n_stats)) + return -EOPNOTSUPP; + ++ *data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (!*data) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, ++ struct ethtool_stats *stats, ++ u64 **data) ++ { ++ const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; ++ int n_stats, ret; ++ ++ if (!phy_ops || !phy_ops->get_sset_count || !phy_ops->get_stats) ++ return -EOPNOTSUPP; ++ ++ n_stats = phy_ops->get_sset_count(phydev); ++ ++ ret = ethtool_vzalloc_stats_array(n_stats, data); ++ if (ret) ++ return ret; ++ ++ stats->n_stats = n_stats; ++ return phy_ops->get_stats(phydev, stats, *data); ++} ++ ++static int ethtool_get_phy_stats_ethtool(struct net_device *dev, ++ struct ethtool_stats *stats, ++ u64 **data) ++{ ++ const struct ethtool_ops *ops = dev->ethtool_ops; ++ int n_stats, ret; ++ ++ if (!ops || !ops->get_sset_count || ops->get_ethtool_phy_stats) ++ return -EOPNOTSUPP; ++ ++ n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ ++ ret = ethtool_vzalloc_stats_array(n_stats, data); ++ if (ret) ++ return ret; ++ ++ stats->n_stats = n_stats; ++ ops->get_ethtool_phy_stats(dev, stats, *data); ++ ++ return 0; ++} ++ ++static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) ++{ ++ struct phy_device *phydev = dev->phydev; ++ struct ethtool_stats stats; ++ u64 *data = NULL; ++ int ret = -EOPNOTSUPP; ++ + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (phydev) ++ ret = ethtool_get_phy_stats_phydev(phydev, &stats, &data); + +- data = vzalloc(array_size(n_stats, sizeof(u64))); +- if (!data) +- return -ENOMEM; ++ if (ret == -EOPNOTSUPP) ++ ret = ethtool_get_phy_stats_ethtool(dev, &stats, &data); + +- if (phydev && !ops->get_ethtool_phy_stats && +- phy_ops && phy_ops->get_stats) { +- ret = phy_ops->get_stats(phydev, &stats, data); +- if (ret < 0) +- goto out; +- } else { +- ops->get_ethtool_phy_stats(dev, &stats, data); +- } ++ if (ret) ++ goto out; + +- ret = -EFAULT; +- if (copy_to_user(useraddr, &stats, sizeof(stats))) ++ if (copy_to_user(useraddr, &stats, sizeof(stats))) { ++ ret = -EFAULT; + goto out; ++ } ++ + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) +- goto out; +- ret = 0; ++ if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ ret = -EFAULT; + + out: + vfree(data); +-- +2.51.0 + diff --git a/queue-6.1/net-hns3-add-vlan-id-validation-before-using.patch b/queue-6.1/net-hns3-add-vlan-id-validation-before-using.patch new file mode 100644 index 0000000000..536a6bb295 --- /dev/null +++ b/queue-6.1/net-hns3-add-vlan-id-validation-before-using.patch @@ -0,0 +1,46 @@ +From ded03f8d30ca55eced75d8a4620e61897e7fe04c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:37 +0800 +Subject: net: hns3: add VLAN id validation before using + +From: Jian Shen + +[ Upstream commit 6ef935e65902bfed53980ad2754b06a284ea8ac1 ] + +Currently, the VLAN id may be used without validation when +receive a VLAN configuration mailbox from VF. The length of +vlan_del_fail_bmap is BITS_TO_LONGS(VLAN_N_VID). It may cause +out-of-bounds memory access once the VLAN id is bigger than +or equal to VLAN_N_VID. + +Therefore, VLAN id needs to be checked to ensure it is within +the range of VLAN_N_VID. + +Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index c45340f26ee49..a92f056b25613 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -10585,6 +10585,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, + bool writen_to_tbl = false; + int ret = 0; + ++ if (vlan_id >= VLAN_N_VID) ++ return -EINVAL; ++ + /* When device is resetting or reset failed, firmware is unable to + * handle mailbox. Just record the vlan id, and remove it after + * reset finished. +-- +2.51.0 + diff --git a/queue-6.1/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch b/queue-6.1/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch new file mode 100644 index 0000000000..770e165eec --- /dev/null +++ b/queue-6.1/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch @@ -0,0 +1,52 @@ +From 05660ecdaa98937f68256461ea77001c91c347be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:35 +0800 +Subject: net: hns3: using the num_tqps in the vf driver to apply for resources + +From: Jian Shen + +[ Upstream commit c2a16269742e176fccdd0ef9c016a233491a49ad ] + +Currently, hdev->htqp is allocated using hdev->num_tqps, and kinfo->tqp +is allocated using kinfo->num_tqps. However, kinfo->num_tqps is set to +min(new_tqps, hdev->num_tqps); Therefore, kinfo->num_tqps may be smaller +than hdev->num_tqps, which causes some hdev->htqp[i] to remain +uninitialized in hclgevf_knic_setup(). + +Thus, this patch allocates hdev->htqp and kinfo->tqp using hdev->num_tqps, +ensuring that the lengths of hdev->htqp and kinfo->tqp are consistent +and that all elements are properly initialized. + +Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-2-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index cff8654354e6d..1c434a19ddc34 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -385,12 +385,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) + new_tqps = kinfo->rss_size * num_tc; + kinfo->num_tqps = min(new_tqps, hdev->num_tqps); + +- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, ++ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, + sizeof(struct hnae3_queue *), GFP_KERNEL); + if (!kinfo->tqp) + return -ENOMEM; + +- for (i = 0; i < kinfo->num_tqps; i++) { ++ for (i = 0; i < hdev->num_tqps; i++) { + hdev->htqp[i].q.handle = &hdev->nic; + hdev->htqp[i].q.tqp_index = i; + kinfo->tqp[i] = &hdev->htqp[i].q; +-- +2.51.0 + diff --git a/queue-6.1/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch b/queue-6.1/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch new file mode 100644 index 0000000000..af8a54d9dc --- /dev/null +++ b/queue-6.1/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch @@ -0,0 +1,49 @@ +From e038afc703494b3d52792c6fce73be102e073ed7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:36 +0800 +Subject: net: hns3: using the num_tqps to check whether tqp_index is out of + range when vf get ring info from mbx + +From: Jian Shen + +[ Upstream commit d180c11aa8a6fa735f9ac2c72c61364a9afc2ba7 ] + +Currently, rss_size = num_tqps / tc_num. If tc_num is 1, then num_tqps +equals rss_size. However, if the tc_num is greater than 1, then rss_size +will be less than num_tqps, causing the tqp_index check for subsequent TCs +using rss_size to always fail. + +This patch uses the num_tqps to check whether tqp_index is out of range, +instead of rss_size. + +Fixes: 326334aad024 ("net: hns3: add a check for tqp_index in hclge_get_ring_chain_from_mbx()") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-3-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index 61e155c4d441e..a961e90a85a67 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx( + return -EINVAL; + + for (i = 0; i < ring_num; i++) { +- if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { ++ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { + dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", + req->msg.param[i].tqp_index, +- vport->nic.kinfo.rss_size - 1U); ++ vport->nic.kinfo.num_tqps - 1U); + return -EINVAL; + } + } +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-create-a-new-profile-for-sfs.patch b/queue-6.1/net-mlx5-create-a-new-profile-for-sfs.patch new file mode 100644 index 0000000000..d04eeec230 --- /dev/null +++ b/queue-6.1/net-mlx5-create-a-new-profile-for-sfs.patch @@ -0,0 +1,139 @@ +From 0cac9a5525c6ec516486244128d86f5835a81828 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Apr 2020 08:27:59 -0500 +Subject: net/mlx5: Create a new profile for SFs + +From: Parav Pandit + +[ Upstream commit 9df839a711aee437390b16ee39cf0b5c1620be6a ] + +Create a new profile for SFs in order to disable the command cache. +Each function command cache consumes ~500KB of memory, when using a +large number of SFs this savings is notable on memory constarined +systems. + +Use a new profile to provide for future differences between SFs and PFs. + +The mr_cache not used for non-PF functions, so it is excluded from the +new profile. + +Signed-off-by: Parav Pandit +Reviewed-by: Bodong Wang +Signed-off-by: Saeed Mahameed +Stable-dep-of: 5846a365fc64 ("net/mlx5: Drain firmware reset in shutdown callback") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 6 +++--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 9 +++++++++ + drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 1 + + drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c | 2 +- + include/linux/mlx5/driver.h | 1 + + 5 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index 4c614a256ee05..ff45b7b5e1c21 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -1833,7 +1833,7 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size, + if (in_size <= 16) + goto cache_miss; + +- for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) { ++ for (i = 0; i < dev->profile.num_cmd_caches; i++) { + ch = &cmd->cache[i]; + if (in_size > ch->max_inbox_size) + continue; +@@ -2129,7 +2129,7 @@ static void destroy_msg_cache(struct mlx5_core_dev *dev) + struct mlx5_cmd_msg *n; + int i; + +- for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) { ++ for (i = 0; i < dev->profile.num_cmd_caches; i++) { + ch = &dev->cmd.cache[i]; + list_for_each_entry_safe(msg, n, &ch->head, list) { + list_del(&msg->list); +@@ -2159,7 +2159,7 @@ static void create_msg_cache(struct mlx5_core_dev *dev) + int k; + + /* Initialize and fill the caches with initial entries */ +- for (k = 0; k < MLX5_NUM_COMMAND_CACHES; k++) { ++ for (k = 0; k < dev->profile.num_cmd_caches; k++) { + ch = &cmd->cache[k]; + spin_lock_init(&ch->lock); + INIT_LIST_HEAD(&ch->head); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index a53f222e3feed..891b625a6dc71 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -103,15 +103,19 @@ enum { + static struct mlx5_profile profile[] = { + [0] = { + .mask = 0, ++ .num_cmd_caches = MLX5_NUM_COMMAND_CACHES, + }, + [1] = { + .mask = MLX5_PROF_MASK_QP_SIZE, + .log_max_qp = 12, ++ .num_cmd_caches = MLX5_NUM_COMMAND_CACHES, ++ + }, + [2] = { + .mask = MLX5_PROF_MASK_QP_SIZE | + MLX5_PROF_MASK_MR_CACHE, + .log_max_qp = LOG_MAX_SUPPORTED_QPS, ++ .num_cmd_caches = MLX5_NUM_COMMAND_CACHES, + .mr_cache[0] = { + .size = 500, + .limit = 250 +@@ -177,6 +181,11 @@ static struct mlx5_profile profile[] = { + .limit = 4 + }, + }, ++ [3] = { ++ .mask = MLX5_PROF_MASK_QP_SIZE, ++ .log_max_qp = LOG_MAX_SUPPORTED_QPS, ++ .num_cmd_caches = 0, ++ }, + }; + + static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +index 7d90f311b8560..07b5c86fc26a4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +@@ -142,6 +142,7 @@ enum mlx5_semaphore_space_address { + }; + + #define MLX5_DEFAULT_PROF 2 ++#define MLX5_SF_PROF 3 + + static inline int mlx5_flexible_inlen(struct mlx5_core_dev *dev, size_t fixed, + size_t item_size, size_t num_items, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +index d6850eb0ed7f4..f314ad1e8c312 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +@@ -28,7 +28,7 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia + mdev->priv.adev_idx = adev->id; + sf_dev->mdev = mdev; + +- err = mlx5_mdev_init(mdev, MLX5_DEFAULT_PROF); ++ err = mlx5_mdev_init(mdev, MLX5_SF_PROF); + if (err) { + mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err); + goto mdev_err; +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index 9af7180eac9e3..0e8705c3a460d 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -755,6 +755,7 @@ enum { + struct mlx5_profile { + u64 mask; + u8 log_max_qp; ++ u8 num_cmd_caches; + struct { + int size; + int limit; +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch b/queue-6.1/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch new file mode 100644 index 0000000000..2624fbc507 --- /dev/null +++ b/queue-6.1/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch @@ -0,0 +1,38 @@ +From 1404950d6768fc05fe21bdd2b2ab0af0e341958b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:10 +0200 +Subject: net/mlx5: Drain firmware reset in shutdown callback + +From: Moshe Shemesh + +[ Upstream commit 5846a365fc6476b02d6766963cf0985520f0385f ] + +Invoke drain_fw_reset() in the shutdown callback to ensure all +firmware reset handling is completed before shutdown proceeds. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 891b625a6dc71..2b89bbd95f9af 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1999,6 +1999,7 @@ static void shutdown(struct pci_dev *pdev) + + mlx5_core_info(dev, "Shutdown was called\n"); + set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); ++ mlx5_drain_fw_reset(dev); + mlx5_drain_health_wq(dev); + err = mlx5_try_fast_unload(dev); + if (err) +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch b/queue-6.1/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch new file mode 100644 index 0000000000..06f664b001 --- /dev/null +++ b/queue-6.1/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch @@ -0,0 +1,45 @@ +From 840bc999354a300f3695d2522e031230b6898e6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:09 +0200 +Subject: net/mlx5: fw reset, clear reset requested on drain_fw_reset + +From: Moshe Shemesh + +[ Upstream commit 89a898d63f6f588acf5c104c65c94a38b68c69a6 ] + +drain_fw_reset() waits for ongoing firmware reset events and blocks new +event handling, but does not clear the reset requested flag, and may +keep sync reset polling. + +To fix it, call mlx5_sync_reset_clear_reset_requested() to clear the +flag, stop sync reset polling, and resume health polling, ensuring +health issues are still detected after the firmware reset drain. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index de130c75de64e..bb62dad48b306 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -534,7 +534,8 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev) + cancel_work_sync(&fw_reset->reset_reload_work); + cancel_work_sync(&fw_reset->reset_now_work); + cancel_work_sync(&fw_reset->reset_abort_work); +- cancel_delayed_work(&fw_reset->reset_timeout_work); ++ if (test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) ++ mlx5_sync_reset_clear_reset_requested(dev, true); + } + + int mlx5_fw_reset_init(struct mlx5_core_dev *dev) +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch b/queue-6.1/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch new file mode 100644 index 0000000000..a19f14ee56 --- /dev/null +++ b/queue-6.1/net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch @@ -0,0 +1,94 @@ +From e242617173f3667f88ad4df389dba2f685f98338 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Jan 2023 15:24:19 +0200 +Subject: net/mlx5: fw_tracer, Add support for unrecognized string + +From: Shay Drory + +[ Upstream commit f7133135235dbd11e7cb5fe62fe5d05ce5e82eeb ] + +In case FW is publishing a string which isn't found in the driver's +string DBs, keep the string as raw data. + +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: b35966042d20 ("net/mlx5: fw_tracer, Validate format string parameters") +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 25 +++++++++++++++++-- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 3ba54ffa54bfe..83a3074a725b1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -460,6 +460,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer, + + tracer_event->event_id = MLX5_GET(tracer_event, trace, event_id); + tracer_event->lost_event = MLX5_GET(tracer_event, trace, lost); ++ tracer_event->out = trace; + + switch (tracer_event->event_id) { + case TRACER_EVENT_TYPE_TIMESTAMP: +@@ -582,6 +583,26 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + mlx5_tracer_clean_message(str_frmt); + } + ++static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_event *tracer_event) ++{ ++ struct tracer_string_format *cur_string; ++ ++ cur_string = mlx5_tracer_message_insert(tracer, tracer_event); ++ if (!cur_string) ++ return -1; ++ ++ cur_string->event_id = tracer_event->event_id; ++ cur_string->timestamp = tracer_event->string_event.timestamp; ++ cur_string->lost = tracer_event->lost_event; ++ cur_string->string = "0x%08x%08x"; ++ cur_string->num_of_params = 2; ++ cur_string->params[0] = upper_32_bits(*tracer_event->out); ++ cur_string->params[1] = lower_32_bits(*tracer_event->out); ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++ return 0; ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -590,7 +611,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (tracer_event->string_event.tdsn == 0) { + cur_string = mlx5_tracer_get_string(tracer, tracer_event); + if (!cur_string) +- return -1; ++ return mlx5_tracer_handle_raw_string(tracer, tracer_event); + + cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); + cur_string->last_param_num = 0; +@@ -605,7 +626,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) { + pr_debug("%s Got string event for unknown string tmsn: %d\n", + __func__, tracer_event->string_event.tmsn); +- return -1; ++ return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 4762b55b0b0ee..3ff412999a3e2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -158,6 +158,7 @@ struct tracer_event { + struct tracer_string_event string_event; + struct tracer_timestamp_event timestamp_event; + }; ++ u64 *out; + }; + + struct mlx5_ifc_tracer_event_bits { +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch b/queue-6.1/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch new file mode 100644 index 0000000000..076f54959f --- /dev/null +++ b/queue-6.1/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch @@ -0,0 +1,84 @@ +From 4ae9860ffa1cf8e0b8b8304ddd7afb0eb7880d80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:12 +0200 +Subject: net/mlx5: fw_tracer, Handle escaped percent properly + +From: Shay Drory + +[ Upstream commit c0289f67f7d6a0dfba0e92cfe661a5c70c8c6e92 ] + +The firmware tracer's format string validation and parameter counting +did not properly handle escaped percent signs (%%). This caused +fw_tracer to count more parameters when trace format strings contained +literal percent characters. + +To fix it, allow %% to pass string validation and skip %% sequences when +counting parameters since they represent literal percent signs rather +than format specifiers. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reported-by: Breno Leitao +Reviewed-by: Moshe Shemesh +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 2ce900b18f705..c216634c8919e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -364,11 +364,11 @@ static bool mlx5_is_valid_spec(const char *str) + while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') + str++; + +- /* Check if it's a valid integer/hex specifier: ++ /* Check if it's a valid integer/hex specifier or %%: + * Valid formats: %x, %d, %i, %u, etc. + */ + if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && +- *str != 'u' && *str != 'c') ++ *str != 'u' && *str != 'c' && *str != '%') + return false; + + return true; +@@ -386,7 +386,11 @@ static bool mlx5_tracer_validate_params(const char *str) + if (!mlx5_is_valid_spec(substr + 1)) + return false; + +- substr = strstr(substr + 1, PARAM_CHAR); ++ if (*(substr + 1) == '%') ++ substr = strstr(substr + 2, PARAM_CHAR); ++ else ++ substr = strstr(substr + 1, PARAM_CHAR); ++ + } + + return true; +@@ -463,11 +467,15 @@ static int mlx5_tracer_get_num_of_params(char *str) + substr = strstr(pstr, VAL_PARM); + } + +- /* count all the % characters */ ++ /* count all the % characters, but skip %% (escaped percent) */ + substr = strstr(str, PARAM_CHAR); + while (substr) { +- num_of_params += 1; +- str = substr + 1; ++ if (*(substr + 1) != '%') { ++ num_of_params += 1; ++ str = substr + 1; ++ } else { ++ str = substr + 2; ++ } + substr = strstr(str, PARAM_CHAR); + } + +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-fw_tracer-validate-format-string-parameters.patch b/queue-6.1/net-mlx5-fw_tracer-validate-format-string-parameters.patch new file mode 100644 index 0000000000..1bae50dee0 --- /dev/null +++ b/queue-6.1/net-mlx5-fw_tracer-validate-format-string-parameters.patch @@ -0,0 +1,195 @@ +From da942431ad05c382ae02cb9382bfa032c856ef71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:11 +0200 +Subject: net/mlx5: fw_tracer, Validate format string parameters + +From: Shay Drory + +[ Upstream commit b35966042d20b14e2d83330049f77deec5229749 ] + +Add validation for format string parameters in the firmware tracer to +prevent potential security vulnerabilities and crashes from malformed +format strings received from firmware. + +The firmware tracer receives format strings from the device firmware and +uses them to format trace messages. Without proper validation, bad +firmware could provide format strings with invalid format specifiers +(e.g., %s, %p, %n) that could lead to crashes, or other undefined +behavior. + +Add mlx5_tracer_validate_params() to validate that all format specifiers +in trace strings are limited to safe integer/hex formats (%x, %d, %i, +%u, %llx, %lx, etc.). Reject strings containing other format types that +could be used to access arbitrary memory or cause crashes. +Invalid format strings are added to the trace output for visibility with +"BAD_FORMAT: " prefix. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Reported-by: Breno Leitao +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 83 ++++++++++++++++--- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 74 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 83a3074a725b1..2ce900b18f705 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -33,6 +33,7 @@ + #include "lib/eq.h" + #include "fw_tracer.h" + #include "fw_tracer_tracepoint.h" ++#include + + static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) + { +@@ -354,6 +355,43 @@ static const char *VAL_PARM = "%llx"; + static const char *REPLACE_64_VAL_PARM = "%x%x"; + static const char *PARAM_CHAR = "%"; + ++static bool mlx5_is_valid_spec(const char *str) ++{ ++ /* Parse format specifiers to find the actual type. ++ * Structure: %[flags][width][.precision][length]type ++ * Skip flags, width, precision & length. ++ */ ++ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') ++ str++; ++ ++ /* Check if it's a valid integer/hex specifier: ++ * Valid formats: %x, %d, %i, %u, etc. ++ */ ++ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && ++ *str != 'u' && *str != 'c') ++ return false; ++ ++ return true; ++} ++ ++static bool mlx5_tracer_validate_params(const char *str) ++{ ++ const char *substr = str; ++ ++ if (!str) ++ return false; ++ ++ substr = strstr(substr, PARAM_CHAR); ++ while (substr) { ++ if (!mlx5_is_valid_spec(substr + 1)) ++ return false; ++ ++ substr = strstr(substr + 1, PARAM_CHAR); ++ } ++ ++ return true; ++} ++ + static int mlx5_tracer_message_hash(u32 message_id) + { + return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); +@@ -413,6 +451,10 @@ static int mlx5_tracer_get_num_of_params(char *str) + char *substr, *pstr = str; + int num_of_params = 0; + ++ /* Validate that all parameters are valid before processing */ ++ if (!mlx5_tracer_validate_params(str)) ++ return -EINVAL; ++ + /* replace %llx with %x%x */ + substr = strstr(pstr, VAL_PARM); + while (substr) { +@@ -564,14 +606,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + { + char tmp[512]; + +- snprintf(tmp, sizeof(tmp), str_frmt->string, +- str_frmt->params[0], +- str_frmt->params[1], +- str_frmt->params[2], +- str_frmt->params[3], +- str_frmt->params[4], +- str_frmt->params[5], +- str_frmt->params[6]); ++ if (str_frmt->invalid_string) ++ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string); ++ else ++ snprintf(tmp, sizeof(tmp), str_frmt->string, ++ str_frmt->params[0], ++ str_frmt->params[1], ++ str_frmt->params[2], ++ str_frmt->params[3], ++ str_frmt->params[4], ++ str_frmt->params[5], ++ str_frmt->params[6]); + + trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, + str_frmt->event_id, tmp); +@@ -603,6 +648,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, + return 0; + } + ++static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_string_format *cur_string) ++{ ++ cur_string->invalid_string = true; ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -613,12 +665,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + +- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); +- cur_string->last_param_num = 0; + cur_string->event_id = tracer_event->event_id; + cur_string->tmsn = tracer_event->string_event.tmsn; + cur_string->timestamp = tracer_event->string_event.timestamp; + cur_string->lost = tracer_event->lost_event; ++ cur_string->last_param_num = 0; ++ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s Invalid format string parameters\n", ++ __func__); ++ mlx5_tracer_handle_bad_format_string(tracer, cur_string); ++ return 0; ++ } + if (cur_string->num_of_params == 0) /* trace with no params */ + list_add_tail(&cur_string->list, &tracer->ready_strings_list); + } else { +@@ -628,6 +686,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + __func__, tracer_event->string_event.tmsn); + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s string parameter of invalid string, dumping\n", ++ __func__); ++ return 0; ++ } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { + pr_debug("%s Number of params exceeds the max (%d)\n", +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 3ff412999a3e2..c57c4f434c36a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -117,6 +117,7 @@ struct tracer_string_format { + struct list_head list; + u32 timestamp; + bool lost; ++ bool invalid_string; + }; + + enum mlx5_fw_tracer_ownership_state { +-- +2.51.0 + diff --git a/queue-6.1/net-openvswitch-fix-middle-attribute-validation-in-p.patch b/queue-6.1/net-openvswitch-fix-middle-attribute-validation-in-p.patch new file mode 100644 index 0000000000..ff56d6423f --- /dev/null +++ b/queue-6.1/net-openvswitch-fix-middle-attribute-validation-in-p.patch @@ -0,0 +1,112 @@ +From 69a69ac03dfe96423c03acdfd012466cce80e025 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:53:32 +0100 +Subject: net: openvswitch: fix middle attribute validation in push_nsh() + action + +From: Ilya Maximets + +[ Upstream commit 5ace7ef87f059d68b5f50837ef3e8a1a4870c36e ] + +The push_nsh() action structure looks like this: + + OVS_ACTION_ATTR_PUSH_NSH(OVS_KEY_ATTR_NSH(OVS_NSH_KEY_ATTR_BASE,...)) + +The outermost OVS_ACTION_ATTR_PUSH_NSH attribute is OK'ed by the +nla_for_each_nested() inside __ovs_nla_copy_actions(). The innermost +OVS_NSH_KEY_ATTR_BASE/MD1/MD2 are OK'ed by the nla_for_each_nested() +inside nsh_key_put_from_nlattr(). But nothing checks if the attribute +in the middle is OK. We don't even check that this attribute is the +OVS_KEY_ATTR_NSH. We just do a double unwrap with a pair of nla_data() +calls - first time directly while calling validate_push_nsh() and the +second time as part of the nla_for_each_nested() macro, which isn't +safe, potentially causing invalid memory access if the size of this +attribute is incorrect. The failure may not be noticed during +validation due to larger netlink buffer, but cause trouble later during +action execution where the buffer is allocated exactly to the size: + + BUG: KASAN: slab-out-of-bounds in nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + Read of size 184 at addr ffff88816459a634 by task a.out/22624 + + CPU: 8 UID: 0 PID: 22624 6.18.0-rc7+ #115 PREEMPT(voluntary) + Call Trace: + + dump_stack_lvl+0x51/0x70 + print_address_description.constprop.0+0x2c/0x390 + kasan_report+0xdd/0x110 + kasan_check_range+0x35/0x1b0 + __asan_memcpy+0x20/0x60 + nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + push_nsh+0x82/0x120 [openvswitch] + do_execute_actions+0x1405/0x2840 [openvswitch] + ovs_execute_actions+0xd5/0x3b0 [openvswitch] + ovs_packet_cmd_execute+0x949/0xdb0 [openvswitch] + genl_family_rcv_msg_doit+0x1d6/0x2b0 + genl_family_rcv_msg+0x336/0x580 + genl_rcv_msg+0x9f/0x130 + netlink_rcv_skb+0x11f/0x370 + genl_rcv+0x24/0x40 + netlink_unicast+0x73e/0xaa0 + netlink_sendmsg+0x744/0xbf0 + __sys_sendto+0x3d6/0x450 + do_syscall_64+0x79/0x2c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + +Let's add some checks that the attribute is properly sized and it's +the only one attribute inside the action. Technically, there is no +real reason for OVS_KEY_ATTR_NSH to be there, as we know that we're +pushing an NSH header already, it just creates extra nesting, but +that's how uAPI works today. So, keeping as it is. + +Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") +Reported-by: Junvy Yang +Signed-off-by: Ilya Maximets +Acked-by: Eelco Chaudron echaudro@redhat.com +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20251204105334.900379-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index d0b6e58720816..d4c8b4aa98b19 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2786,13 +2786,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, + return err; + } + +-static bool validate_push_nsh(const struct nlattr *attr, bool log) ++static bool validate_push_nsh(const struct nlattr *a, bool log) + { ++ struct nlattr *nsh_key = nla_data(a); + struct sw_flow_match match; + struct sw_flow_key key; + ++ /* There must be one and only one NSH header. */ ++ if (!nla_ok(nsh_key, nla_len(a)) || ++ nla_total_size(nla_len(nsh_key)) != nla_len(a) || ++ nla_type(nsh_key) != OVS_KEY_ATTR_NSH) ++ return false; ++ + ovs_match_init(&match, &key, true, NULL); +- return !nsh_key_put_from_nlattr(attr, &match, false, true, log); ++ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log); + } + + /* Return false if there are any non-masked bits set. +@@ -3346,7 +3353,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, + return -EINVAL; + } + mac_proto = MAC_PROTO_NONE; +- if (!validate_push_nsh(nla_data(a), log)) ++ if (!validate_push_nsh(a, log)) + return -EINVAL; + break; + +-- +2.51.0 + diff --git a/queue-6.1/net-sched-ets-always-remove-class-from-active-list-b.patch b/queue-6.1/net-sched-ets-always-remove-class-from-active-list-b.patch new file mode 100644 index 0000000000..f2f39e1884 --- /dev/null +++ b/queue-6.1/net-sched-ets-always-remove-class-from-active-list-b.patch @@ -0,0 +1,232 @@ +From 524ee2b989d793bde7fa2116e774a29618b4b1bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: net/sched: ets: Always remove class from active list before deleting + in ets_qdisc_change + +From: Jamal Hadi Salim + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 9873f4ae90c3a..b732d09ede99a 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -652,7 +652,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.51.0 + diff --git a/queue-6.1/net-sched-ets-remove-drr-class-from-the-active-list-.patch b/queue-6.1/net-sched-ets-remove-drr-class-from-the-active-list-.patch new file mode 100644 index 0000000000..30faa7d710 --- /dev/null +++ b/queue-6.1/net-sched-ets-remove-drr-class-from-the-active-list-.patch @@ -0,0 +1,88 @@ +From e1e032ab5b9a273c478cf8b203798e23cea96831 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:01:24 -0300 +Subject: net/sched: ets: Remove drr class from the active list if it changes + to strict + +From: Victor Nogueira + +[ Upstream commit b1e125ae425aba9b45252e933ca8df52a843ec70 ] + +Whenever a user issues an ets qdisc change command, transforming a +drr class into a strict one, the ets code isn't checking whether that +class was in the active list and removing it. This means that, if a +user changes a strict class (which was in the active list) back to a drr +one, that class will be added twice to the active list [1]. + +Doing so with the following commands: + +tc qdisc add dev lo root handle 1: ets bands 2 strict 1 +tc qdisc add dev lo parent 1:2 handle 20: \ + tbf rate 8bit burst 100b latency 1s +tc filter add dev lo parent 1: basic classid 1:2 +ping -c1 -W0.01 -s 56 127.0.0.1 +tc qdisc change dev lo root handle 1: ets bands 2 strict 2 +tc qdisc change dev lo root handle 1: ets bands 2 strict 1 +ping -c1 -W0.01 -s 56 127.0.0.1 + +Will trigger the following splat with list debug turned on: + +[ 59.279014][ T365] ------------[ cut here ]------------ +[ 59.279452][ T365] list_add double add: new=ffff88801d60e350, prev=ffff88801d60e350, next=ffff88801d60e2c0. +[ 59.280153][ T365] WARNING: CPU: 3 PID: 365 at lib/list_debug.c:35 __list_add_valid_or_report+0x17f/0x220 +[ 59.280860][ T365] Modules linked in: +[ 59.281165][ T365] CPU: 3 UID: 0 PID: 365 Comm: tc Not tainted 6.18.0-rc7-00105-g7e9f13163c13-dirty #239 PREEMPT(voluntary) +[ 59.281977][ T365] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 59.282391][ T365] RIP: 0010:__list_add_valid_or_report+0x17f/0x220 +[ 59.282842][ T365] Code: 89 c6 e8 d4 b7 0d ff 90 0f 0b 90 90 31 c0 e9 31 ff ff ff 90 48 c7 c7 e0 a0 22 9f 48 89 f2 48 89 c1 4c 89 c6 e8 b2 b7 0d ff 90 <0f> 0b 90 90 31 c0 e9 0f ff ff ff 48 89 f7 48 89 44 24 10 4c 89 44 +... +[ 59.288812][ T365] Call Trace: +[ 59.289056][ T365] +[ 59.289224][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.289546][ T365] ets_qdisc_change+0xd2b/0x1e80 +[ 59.289891][ T365] ? __lock_acquire+0x7e7/0x1be0 +[ 59.290223][ T365] ? __pfx_ets_qdisc_change+0x10/0x10 +[ 59.290546][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.290898][ T365] ? __mutex_trylock_common+0xda/0x240 +[ 59.291228][ T365] ? __pfx___mutex_trylock_common+0x10/0x10 +[ 59.291655][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.291993][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.292313][ T365] ? trace_contention_end+0xc8/0x110 +[ 59.292656][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293022][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293351][ T365] tc_modify_qdisc+0x63a/0x1cf0 + +Fix this by always checking and removing an ets class from the active list +when changing it to strict. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/net/sched/sch_ets.c?id=ce052b9402e461a9aded599f5b47e76bc727f7de#n663 + +Fixes: cd9b50adc6bb9 ("net/sched: ets: fix crash when flipping from 'strict' to 'quantum'") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Reviewed-by: Petr Machata +Link: https://patch.msgid.link/20251208190125.1868423-1-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index b732d09ede99a..6ff619277ffd9 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -664,6 +664,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nstrict; i < nstrict; i++) { ++ if (cl_is_active(&q->classes[i])) ++ list_del_init(&q->classes[i].alist); ++ } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + +-- +2.51.0 + diff --git a/queue-6.1/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch b/queue-6.1/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch new file mode 100644 index 0000000000..7fb0a38464 --- /dev/null +++ b/queue-6.1/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch @@ -0,0 +1,90 @@ +From a3a4e4576deabf2366a38931c1b22a019802fc4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 12:58:01 +0100 +Subject: netfilter: nf_conncount: fix leaked ct in error paths + +From: Fernando Fernandez Mancera + +[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ] + +There are some situations where ct might be leaked as error paths are +skipping the refcounted check and return immediately. In order to solve +it make sure that the check is always called. + +Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conncount.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index 97b631a81484d..c00b8e522c5a7 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net, + struct nf_conn *found_ct; + unsigned int collect = 0; + bool refcounted = false; ++ int err = 0; + + if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- if (refcounted) +- nf_ct_put(ct); +- return -EEXIST; ++ err = -EEXIST; ++ goto out_put; + } + + if ((u32)jiffies == list->last_gc) +@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net, + } + + add_new_node: +- if (WARN_ON_ONCE(list->count > INT_MAX)) +- return -EOVERFLOW; ++ if (WARN_ON_ONCE(list->count > INT_MAX)) { ++ err = -EOVERFLOW; ++ goto out_put; ++ } + + conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); +- if (conn == NULL) +- return -ENOMEM; ++ if (conn == NULL) { ++ err = -ENOMEM; ++ goto out_put; ++ } + + conn->tuple = tuple; + conn->zone = *zone; +@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net, + out_put: + if (refcounted) + nf_ct_put(ct); +- return 0; ++ return err; + } + + int nf_conncount_add_skb(struct net *net, +@@ -446,11 +450,10 @@ insert_tree(struct net *net, + + rb_link_node_rcu(&rbconn->node, parent, rbnode); + rb_insert_color(&rbconn->node, root); +- +- if (refcounted) +- nf_ct_put(ct); + } + out_unlock: ++ if (refcounted) ++ nf_ct_put(ct); + spin_unlock_bh(&nf_conncount_locks[hash]); + return count; + } +-- +2.51.0 + diff --git a/queue-6.1/netrom-fix-memory-leak-in-nr_sendmsg.patch b/queue-6.1/netrom-fix-memory-leak-in-nr_sendmsg.patch new file mode 100644 index 0000000000..5de64437ab --- /dev/null +++ b/queue-6.1/netrom-fix-memory-leak-in-nr_sendmsg.patch @@ -0,0 +1,74 @@ +From 22bf9575987cf8ff72992b14f4bafa69f592f6da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 12:13:15 +0800 +Subject: netrom: Fix memory leak in nr_sendmsg() + +From: Wang Liang + +[ Upstream commit 613d12dd794e078be8ff3cf6b62a6b9acf7f4619 ] + +syzbot reported a memory leak [1]. + +When function sock_alloc_send_skb() return NULL in nr_output(), the +original skb is not freed, which was allocated in nr_sendmsg(). Fix this +by freeing it before return. + +[1] +BUG: memory leak +unreferenced object 0xffff888129f35500 (size 240): + comm "syz.0.17", pid 6119, jiffies 4294944652 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 10 52 28 81 88 ff ff ..........R(.... + backtrace (crc 1456a3e4): + kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline] + slab_post_alloc_hook mm/slub.c:4983 [inline] + slab_alloc_node mm/slub.c:5288 [inline] + kmem_cache_alloc_node_noprof+0x36f/0x5e0 mm/slub.c:5340 + __alloc_skb+0x203/0x240 net/core/skbuff.c:660 + alloc_skb include/linux/skbuff.h:1383 [inline] + alloc_skb_with_frags+0x69/0x3f0 net/core/skbuff.c:6671 + sock_alloc_send_pskb+0x379/0x3e0 net/core/sock.c:2965 + sock_alloc_send_skb include/net/sock.h:1859 [inline] + nr_sendmsg+0x287/0x450 net/netrom/af_netrom.c:1105 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg net/socket.c:742 [inline] + sock_write_iter+0x293/0x2a0 net/socket.c:1195 + new_sync_write fs/read_write.c:593 [inline] + vfs_write+0x45d/0x710 fs/read_write.c:686 + ksys_write+0x143/0x170 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xa4/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7abc36bbbb6d7d40b58 +Tested-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20251129041315.1550766-1-wangliang74@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_out.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 5e531394a724b..2b3cbceb0b52d 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) + frontlen = skb_headroom(skb); + + while (skb->len > 0) { +- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) ++ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) { ++ kfree_skb(skb); + return; ++ } + + skb_reserve(skbn, frontlen); + +-- +2.51.0 + diff --git a/queue-6.1/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch b/queue-6.1/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch new file mode 100644 index 0000000000..e087930113 --- /dev/null +++ b/queue-6.1/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch @@ -0,0 +1,37 @@ +From 20e038b89ffdf75033031de4a9e483bc363bbcb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 09:56:39 +0300 +Subject: nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() + +From: Dan Carpenter + +[ Upstream commit 885bebac9909994050bbbeed0829c727e42bd1b7 ] + +Set the error code if "transferred != sizeof(cmd)" instead of +returning success. + +Fixes: dbafc28955fa ("NFC: pn533: don't send USB data off of the stack") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aTfIJ9tZPmeUF4W1@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c +index a187f0e0b0f7d..9e079be43583e 100644 +--- a/drivers/nfc/pn533/usb.c ++++ b/drivers/nfc/pn533/usb.c +@@ -407,7 +407,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) + if (rc || (transferred != sizeof(cmd))) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); +- return rc; ++ return rc ?: -EINVAL; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); +-- +2.51.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 5465e73a07..742c94f02e 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -245,3 +245,27 @@ smb-server-fix-return-value-of-smb2_ioctl.patch ksmbd-fix-use-after-free-in-ksmbd_tree_connect_put-u.patch bluetooth-btusb-add-new-vid-pid-13d3-3533-for-rtl882.patch gfs2-fix-use-of-bio_chain.patch +netrom-fix-memory-leak-in-nr_sendmsg.patch +net-sched-ets-always-remove-class-from-active-list-b.patch +ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch +mlxsw-spectrum_router-fix-neighbour-use-after-free.patch +mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch +net-openvswitch-fix-middle-attribute-validation-in-p.patch +broadcom-b44-prevent-uninitialized-value-usage.patch +netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch +ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch +caif-fix-integer-underflow-in-cffrml_receive.patch +net-sched-ets-remove-drr-class-from-the-active-list-.patch +nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch +net-ethtool-ioctl-remove-if-n_stats-checks-from-etht.patch +net-ethtool-ioctl-split-ethtool_get_phy_stats-into-m.patch +ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch +net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch +net-mlx5-create-a-new-profile-for-sfs.patch +net-mlx5-drain-firmware-reset-in-shutdown-callback.patch +net-mlx5-fw_tracer-add-support-for-unrecognized-stri.patch +net-mlx5-fw_tracer-validate-format-string-parameters.patch +net-mlx5-fw_tracer-handle-escaped-percent-properly.patch +net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch +net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch +net-hns3-add-vlan-id-validation-before-using.patch diff --git a/queue-6.12/bnxt_en-fix-xdp_tx-path.patch b/queue-6.12/bnxt_en-fix-xdp_tx-path.patch new file mode 100644 index 0000000000..3b74fed2d5 --- /dev/null +++ b/queue-6.12/bnxt_en-fix-xdp_tx-path.patch @@ -0,0 +1,74 @@ +From cd9c6fc2ac9e6ac2af40f7db86a994d8241d72eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 16:30:24 -0800 +Subject: bnxt_en: Fix XDP_TX path + +From: Michael Chan + +[ Upstream commit 0373d5c387f24de749cc22e694a14b3a7c7eb515 ] + +For XDP_TX action in bnxt_rx_xdp(), clearing of the event flags is not +correct. __bnxt_poll_work() -> bnxt_rx_pkt() -> bnxt_rx_xdp() may be +looping within NAPI and some event flags may be set in earlier +iterations. In particular, if BNXT_TX_EVENT is set earlier indicating +some XDP_TX packets are ready and pending, it will be cleared if it is +XDP_TX action again. Normally, we will set BNXT_TX_EVENT again when we +successfully call __bnxt_xmit_xdp(). But if the TX ring has no more +room, the flag will not be set. This will cause the TX producer to be +ahead but the driver will not hit the TX doorbell. + +For multi-buf XDP_TX, there is no need to clear the event flags and set +BNXT_AGG_EVENT. The BNXT_AGG_EVENT flag should have been set earlier in +bnxt_rx_pkt(). + +The visible symptom of this is that the RX ring associated with the +TX XDP ring will eventually become empty and all packets will be dropped. +Because this condition will cause the driver to not refill the RX ring +seeing that the TX ring has forever pending XDP_TX packets. + +The fix is to only clear BNXT_RX_EVENT when we have successfully +called __bnxt_xmit_xdp(). + +Fixes: 7f0a168b0441 ("bnxt_en: Add completion ring pointer in TX and RX ring structures") +Reported-by: Pavel Dubovitsky +Reviewed-by: Andy Gospodarek +Reviewed-by: Pavan Chebbi +Reviewed-by: Kalesh AP +Signed-off-by: Michael Chan +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20251203003024.2246699-1-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +index 844812bd65363..fa3c6515cc4d6 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +@@ -268,13 +268,11 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, + case XDP_TX: + rx_buf = &rxr->rx_buf_ring[cons]; + mapping = rx_buf->mapping - bp->rx_dma_offset; +- *event &= BNXT_TX_CMP_EVENT; + + if (unlikely(xdp_buff_has_frags(xdp))) { + struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); + + tx_needed += sinfo->nr_frags; +- *event = BNXT_AGG_EVENT; + } + + if (tx_avail < tx_needed) { +@@ -287,6 +285,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, + dma_sync_single_for_device(&pdev->dev, mapping + offset, *len, + bp->rx_dir); + ++ *event &= ~BNXT_RX_EVENT; + *event |= BNXT_TX_EVENT; + __bnxt_xmit_xdp(bp, txr, mapping + offset, *len, + NEXT_RX(rxr->rx_prod), xdp); +-- +2.51.0 + diff --git a/queue-6.12/broadcom-b44-prevent-uninitialized-value-usage.patch b/queue-6.12/broadcom-b44-prevent-uninitialized-value-usage.patch new file mode 100644 index 0000000000..ac9d7eb722 --- /dev/null +++ b/queue-6.12/broadcom-b44-prevent-uninitialized-value-usage.patch @@ -0,0 +1,45 @@ +From 8b63725595f550cbf34418aab9f77b155c88fb46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 18:58:16 +0300 +Subject: broadcom: b44: prevent uninitialized value usage + +From: Alexey Simakov + +[ Upstream commit 50b3db3e11864cb4e18ff099cfb38e11e7f87a68 ] + +On execution path with raised B44_FLAG_EXTERNAL_PHY, b44_readphy() +leaves bmcr value uninitialized and it is used later in the code. + +Add check of this flag at the beginning of the b44_nway_reset() and +exit early of the function with restarting autonegotiation if an +external PHY is used. + +Fixes: 753f492093da ("[B44]: port to native ssb support") +Reviewed-by: Jonas Gorski +Reviewed-by: Andrew Lunn +Signed-off-by: Alexey Simakov +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20251205155815.4348-1-bigalex934@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/b44.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c +index e5809ad5eb827..29f0de9e31545 100644 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -1789,6 +1789,9 @@ static int b44_nway_reset(struct net_device *dev) + u32 bmcr; + int r; + ++ if (bp->flags & B44_FLAG_EXTERNAL_PHY) ++ return phy_ethtool_nway_reset(dev); ++ + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); +-- +2.51.0 + diff --git a/queue-6.12/caif-fix-integer-underflow-in-cffrml_receive.patch b/queue-6.12/caif-fix-integer-underflow-in-cffrml_receive.patch new file mode 100644 index 0000000000..37cfa07d9b --- /dev/null +++ b/queue-6.12/caif-fix-integer-underflow-in-cffrml_receive.patch @@ -0,0 +1,58 @@ +From 412acda7a1994d5217023c1330cf182c056a02c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 21:30:47 +0800 +Subject: caif: fix integer underflow in cffrml_receive() + +From: Junrui Luo + +[ Upstream commit 8a11ff0948b5ad09b71896b7ccc850625f9878d1 ] + +The cffrml_receive() function extracts a length field from the packet +header and, when FCS is disabled, subtracts 2 from this length without +validating that len >= 2. + +If an attacker sends a malicious packet with a length field of 0 or 1 +to an interface with FCS disabled, the subtraction causes an integer +underflow. + +This can lead to memory exhaustion and kernel instability, potential +information disclosure if padding contains uninitialized kernel memory. + +Fix this by validating that len >= 2 before performing the subtraction. + +Reported-by: Yuhao Jiang +Reported-by: Junrui Luo +Fixes: b482cd2053e3 ("net-caif: add CAIF core protocol stack") +Signed-off-by: Junrui Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/SYBPR01MB7881511122BAFEA8212A1608AFA6A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/caif/cffrml.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c +index 6651a8dc62e04..d4d63586053ad 100644 +--- a/net/caif/cffrml.c ++++ b/net/caif/cffrml.c +@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) + len = le16_to_cpu(tmp); + + /* Subtract for FCS on length if FCS is not used. */ +- if (!this->dofcs) ++ if (!this->dofcs) { ++ if (len < 2) { ++ ++cffrml_rcv_error; ++ pr_err("Invalid frame length (%d)\n", len); ++ cfpkt_destroy(pkt); ++ return -EPROTO; ++ } + len -= 2; ++ } + + if (cfpkt_setlen(pkt, len) < 0) { + ++cffrml_rcv_error; +-- +2.51.0 + diff --git a/queue-6.12/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch b/queue-6.12/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch new file mode 100644 index 0000000000..06621321f6 --- /dev/null +++ b/queue-6.12/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch @@ -0,0 +1,159 @@ +From e525981fac6bfe534128bfc18a6e5f08d289dd53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 14:19:01 +0200 +Subject: ethtool: Avoid overflowing userspace buffer on stats query + +From: Gal Pressman + +[ Upstream commit 7b07be1ff1cb6c49869910518650e8d0abc7d25f ] + +The ethtool -S command operates across three ioctl calls: +ETHTOOL_GSSET_INFO for the size, ETHTOOL_GSTRINGS for the names, and +ETHTOOL_GSTATS for the values. + +If the number of stats changes between these calls (e.g., due to device +reconfiguration), userspace's buffer allocation will be incorrect, +potentially leading to buffer overflow. + +Drivers are generally expected to maintain stable stat counts, but some +drivers (e.g., mlx5, bnx2x, bna, ksz884x) use dynamic counters, making +this scenario possible. + +Some drivers try to handle this internally: +- bnad_get_ethtool_stats() returns early in case stats.n_stats is not + equal to the driver's stats count. +- micrel/ksz884x also makes sure not to write anything beyond + stats.n_stats and overflow the buffer. + +However, both use stats.n_stats which is already assigned with the value +returned from get_sset_count(), hence won't solve the issue described +here. + +Change ethtool_get_strings(), ethtool_get_stats(), +ethtool_get_phy_stats() to not return anything in case of a mismatch +between userspace's size and get_sset_size(), to prevent buffer +overflow. +The returned n_stats value will be equal to zero, to reflect that +nothing has been returned. + +This could result in one of two cases when using upstream ethtool, +depending on when the size change is detected: +1. When detected in ethtool_get_strings(): + # ethtool -S eth2 + no stats available + +2. When detected in get stats, all stats will be reported as zero. + +Both cases are presumably transient, and a subsequent ethtool call +should succeed. + +Other than the overflow avoidance, these two cases are very evident (no +output/cleared stats), which is arguably better than presenting +incorrect/shifted stats. +I also considered returning an error instead of a "silent" response, but +that seems more destructive towards userspace apps. + +Notes: +- This patch does not claim to fix the inherent race, it only makes sure + that we do not overflow the userspace buffer, and makes for a more + predictable behavior. + +- RTNL lock is held during each ioctl, the race window exists between + the separate ioctl calls when the lock is released. + +- Userspace ethtool always fills stats.n_stats, but it is likely that + these stats ioctls are implemented in other userspace applications + which might not fill it. The added code checks that it's not zero, + to prevent any regressions. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Dragos Tatulea +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Link: https://patch.msgid.link/20251208121901.3203692-1-gal@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 8b9692c35e706..67fba88f60984 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2231,7 +2231,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + return -ENOMEM; + WARN_ON_ONCE(!ret); + +- gstrings.len = ret; ++ if (gstrings.len && gstrings.len != ret) ++ gstrings.len = 0; ++ else ++ gstrings.len = ret; + + if (gstrings.len) { + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); +@@ -2353,10 +2356,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (stats.n_stats && stats.n_stats != n_stats) ++ stats.n_stats = 0; ++ else ++ stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (stats.n_stats) { ++ data = vzalloc(array_size(stats.n_stats, sizeof(u64))); + if (!data) + return -ENOMEM; + ops->get_ethtool_stats(dev, &stats, data); +@@ -2368,7 +2374,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + goto out; + ret = 0; + +@@ -2404,6 +2412,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, + return -EOPNOTSUPP; + + n_stats = phy_ops->get_sset_count(phydev); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2424,6 +2436,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev, + return -EOPNOTSUPP; + + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2460,7 +2476,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + } + + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + ret = -EFAULT; + + out: +-- +2.51.0 + diff --git a/queue-6.12/iommufd-selftest-add-coverage-for-reporting-max_pasi.patch b/queue-6.12/iommufd-selftest-add-coverage-for-reporting-max_pasi.patch new file mode 100644 index 0000000000..c638b435a9 --- /dev/null +++ b/queue-6.12/iommufd-selftest-add-coverage-for-reporting-max_pasi.patch @@ -0,0 +1,153 @@ +From 383b6ebedeaa085892b94ce2a66d1550321d093f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 11:01:43 -0700 +Subject: iommufd/selftest: Add coverage for reporting max_pasid_log2 via + IOMMU_HW_INFO + +From: Yi Liu + +[ Upstream commit 6d9500bb1ff8c7f9c3ce199521c41aa41e8fd994 ] + +IOMMU_HW_INFO is extended to report max_pasid_log2, hence add coverage +for it. + +Link: https://patch.msgid.link/r/20250321180143.8468-6-yi.l.liu@intel.com +Reviewed-by: Nicolin Chen +Tested-by: Nicolin Chen +Signed-off-by: Yi Liu +Signed-off-by: Jason Gunthorpe +Stable-dep-of: 5b244b077c0b ("iommufd/selftest: Make it clearer to gcc that the access is not out of bounds") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/iommu/iommufd.c | 18 ++++++++++++++++++ + .../testing/selftests/iommu/iommufd_fail_nth.c | 3 ++- + tools/testing/selftests/iommu/iommufd_utils.h | 17 +++++++++++++---- + 3 files changed, 33 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c +index 7a535c590245f..92c6020c15fa1 100644 +--- a/tools/testing/selftests/iommu/iommufd.c ++++ b/tools/testing/selftests/iommu/iommufd.c +@@ -194,12 +194,14 @@ FIXTURE(iommufd_ioas) + uint32_t hwpt_id; + uint32_t device_id; + uint64_t base_iova; ++ uint32_t device_pasid_id; + }; + + FIXTURE_VARIANT(iommufd_ioas) + { + unsigned int mock_domains; + unsigned int memory_limit; ++ bool pasid_capable; + }; + + FIXTURE_SETUP(iommufd_ioas) +@@ -222,6 +224,12 @@ FIXTURE_SETUP(iommufd_ioas) + &self->hwpt_id, &self->device_id); + self->base_iova = MOCK_APERTURE_START; + } ++ ++ if (variant->pasid_capable) ++ test_cmd_mock_domain_flags(self->ioas_id, ++ MOCK_FLAGS_DEVICE_PASID, ++ NULL, NULL, ++ &self->device_pasid_id); + } + + FIXTURE_TEARDOWN(iommufd_ioas) +@@ -237,6 +245,7 @@ FIXTURE_VARIANT_ADD(iommufd_ioas, no_domain) + FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain) + { + .mock_domains = 1, ++ .pasid_capable = true, + }; + + FIXTURE_VARIANT_ADD(iommufd_ioas, two_mock_domain) +@@ -602,6 +611,8 @@ TEST_F(iommufd_ioas, get_hw_info) + } buffer_smaller; + + if (self->device_id) { ++ uint8_t max_pasid = 0; ++ + /* Provide a zero-size user_buffer */ + test_cmd_get_hw_info(self->device_id, NULL, 0); + /* Provide a user_buffer with exact size */ +@@ -616,6 +627,13 @@ TEST_F(iommufd_ioas, get_hw_info) + * the fields within the size range still gets updated. + */ + test_cmd_get_hw_info(self->device_id, &buffer_smaller, sizeof(buffer_smaller)); ++ test_cmd_get_hw_info_pasid(self->device_id, &max_pasid); ++ ASSERT_EQ(0, max_pasid); ++ if (variant->pasid_capable) { ++ test_cmd_get_hw_info_pasid(self->device_pasid_id, ++ &max_pasid); ++ ASSERT_EQ(MOCK_PASID_WIDTH, max_pasid); ++ } + } else { + test_err_get_hw_info(ENOENT, self->device_id, + &buffer_exact, sizeof(buffer_exact)); +diff --git a/tools/testing/selftests/iommu/iommufd_fail_nth.c b/tools/testing/selftests/iommu/iommufd_fail_nth.c +index c5d5e69452b01..62d02556b34cc 100644 +--- a/tools/testing/selftests/iommu/iommufd_fail_nth.c ++++ b/tools/testing/selftests/iommu/iommufd_fail_nth.c +@@ -612,7 +612,8 @@ TEST_FAIL_NTH(basic_fail_nth, device) + &idev_id)) + return -1; + +- if (_test_cmd_get_hw_info(self->fd, idev_id, &info, sizeof(info), NULL)) ++ if (_test_cmd_get_hw_info(self->fd, idev_id, &info, ++ sizeof(info), NULL, NULL)) + return -1; + + if (_test_cmd_hwpt_alloc(self->fd, idev_id, ioas_id, 0, 0, &hwpt_id, +diff --git a/tools/testing/selftests/iommu/iommufd_utils.h b/tools/testing/selftests/iommu/iommufd_utils.h +index 40f6f14ce136f..8994b43e86f89 100644 +--- a/tools/testing/selftests/iommu/iommufd_utils.h ++++ b/tools/testing/selftests/iommu/iommufd_utils.h +@@ -638,7 +638,8 @@ static void teardown_iommufd(int fd, struct __test_metadata *_metadata) + + /* @data can be NULL */ + static int _test_cmd_get_hw_info(int fd, __u32 device_id, void *data, +- size_t data_len, uint32_t *capabilities) ++ size_t data_len, uint32_t *capabilities, ++ uint8_t *max_pasid) + { + struct iommu_test_hw_info *info = (struct iommu_test_hw_info *)data; + struct iommu_hw_info cmd = { +@@ -683,6 +684,9 @@ static int _test_cmd_get_hw_info(int fd, __u32 device_id, void *data, + assert(!info->flags); + } + ++ if (max_pasid) ++ *max_pasid = cmd.out_max_pasid_log2; ++ + if (capabilities) + *capabilities = cmd.out_capabilities; + +@@ -691,14 +695,19 @@ static int _test_cmd_get_hw_info(int fd, __u32 device_id, void *data, + + #define test_cmd_get_hw_info(device_id, data, data_len) \ + ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, data, \ +- data_len, NULL)) ++ data_len, NULL, NULL)) + + #define test_err_get_hw_info(_errno, device_id, data, data_len) \ + EXPECT_ERRNO(_errno, _test_cmd_get_hw_info(self->fd, device_id, data, \ +- data_len, NULL)) ++ data_len, NULL, NULL)) + + #define test_cmd_get_hw_capabilities(device_id, caps, mask) \ +- ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, NULL, 0, &caps)) ++ ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, NULL, \ ++ 0, &caps, NULL)) ++ ++#define test_cmd_get_hw_info_pasid(device_id, max_pasid) \ ++ ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, NULL, \ ++ 0, NULL, max_pasid)) + + static int _test_ioctl_fault_alloc(int fd, __u32 *fault_id, __u32 *fault_fd) + { +-- +2.51.0 + diff --git a/queue-6.12/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch b/queue-6.12/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch new file mode 100644 index 0000000000..793c85e061 --- /dev/null +++ b/queue-6.12/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch @@ -0,0 +1,57 @@ +From 8636abbbf8eb295e774b51690bf38718de203e61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Dec 2025 11:53:40 -0400 +Subject: iommufd/selftest: Check for overflow in IOMMU_TEST_OP_ADD_RESERVED + +From: Jason Gunthorpe + +[ Upstream commit e6a973af11135439de32ece3b9cbe3bfc043bea8 ] + +syzkaller found it could overflow math in the test infrastructure and +cause a WARN_ON by corrupting the reserved interval tree. This only +effects test kernels with CONFIG_IOMMUFD_TEST. + +Validate the user input length in the test ioctl. + +Fixes: f4b20bb34c83 ("iommufd: Add kernel support for testing iommufd") +Link: https://patch.msgid.link/r/0-v1-cd99f6049ba5+51-iommufd_syz_add_resv_jgg@nvidia.com +Reviewed-by: Samiullah Khawaja +Reviewed-by: Kevin Tian +Tested-by: Yi Liu +Reported-by: syzbot+57fdb0cf6a0c5d1f15a2@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/69368129.a70a0220.38f243.008f.GAE@google.com +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/selftest.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c +index 540437be168a0..aed260d4a93cc 100644 +--- a/drivers/iommu/iommufd/selftest.c ++++ b/drivers/iommu/iommufd/selftest.c +@@ -836,14 +836,20 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd, + unsigned int mockpt_id, + unsigned long start, size_t length) + { ++ unsigned long last; + struct iommufd_ioas *ioas; + int rc; + ++ if (!length) ++ return -EINVAL; ++ if (check_add_overflow(start, length - 1, &last)) ++ return -EOVERFLOW; ++ + ioas = iommufd_get_ioas(ucmd->ictx, mockpt_id); + if (IS_ERR(ioas)) + return PTR_ERR(ioas); + down_write(&ioas->iopt.iova_rwsem); +- rc = iopt_reserve_iova(&ioas->iopt, start, start + length - 1, NULL); ++ rc = iopt_reserve_iova(&ioas->iopt, start, last, NULL); + up_write(&ioas->iopt.iova_rwsem); + iommufd_put_object(ucmd->ictx, &ioas->obj); + return rc; +-- +2.51.0 + diff --git a/queue-6.12/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch b/queue-6.12/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch new file mode 100644 index 0000000000..355e4ed208 --- /dev/null +++ b/queue-6.12/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch @@ -0,0 +1,71 @@ +From 0f45c64ae033edbe6672097a864f3f22cf725ee7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 14:56:12 -0400 +Subject: iommufd/selftest: Make it clearer to gcc that the access is not out + of bounds + +From: Jason Gunthorpe + +[ Upstream commit 5b244b077c0b0e76573fbb9542cf038e42368901 ] + +GCC gets a bit confused and reports: + + In function '_test_cmd_get_hw_info', + inlined from 'iommufd_ioas_get_hw_info' at iommufd.c:779:3, + inlined from 'wrapper_iommufd_ioas_get_hw_info' at iommufd.c:752:1: +>> iommufd_utils.h:804:37: warning: array subscript 'struct iommu_test_hw_info[0]' is partly outside array bounds of 'struct iommu_test_hw_info_buffer_smaller[1]' [-Warray-bounds=] + 804 | assert(!info->flags); + | ~~~~^~~~~~~ + iommufd.c: In function 'wrapper_iommufd_ioas_get_hw_info': + iommufd.c:761:11: note: object 'buffer_smaller' of size 4 + 761 | } buffer_smaller; + | ^~~~~~~~~~~~~~ + +While it is true that "struct iommu_test_hw_info[0]" is partly out of +bounds of the input pointer, it is not true that info->flags is out of +bounds. Unclear why it warns on this. + +Reuse an existing properly sized stack buffer and pass a truncated length +instead to test the same thing. + +Fixes: af4fde93c319 ("iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl") +Link: https://patch.msgid.link/r/0-v1-63a2cffb09da+4486-iommufd_gcc_bounds_jgg@nvidia.com +Reviewed-by: Kevin Tian +Reviewed-by: Nicolin Chen +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202512032344.kaAcKFIM-lkp@intel.com/ +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/iommu/iommufd.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c +index b678b24f5a142..6f99268365338 100644 +--- a/tools/testing/selftests/iommu/iommufd.c ++++ b/tools/testing/selftests/iommu/iommufd.c +@@ -606,9 +606,6 @@ TEST_F(iommufd_ioas, get_hw_info) + struct iommu_test_hw_info info; + uint64_t trailing_bytes; + } buffer_larger; +- struct iommu_test_hw_info_buffer_smaller { +- __u32 flags; +- } buffer_smaller; + + if (self->device_id) { + uint8_t max_pasid = 0; +@@ -640,8 +637,9 @@ TEST_F(iommufd_ioas, get_hw_info) + * the fields within the size range still gets updated. + */ + test_cmd_get_hw_info(self->device_id, +- IOMMU_HW_INFO_TYPE_DEFAULT, +- &buffer_smaller, sizeof(buffer_smaller)); ++ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact, ++ offsetofend(struct iommu_test_hw_info, ++ flags)); + test_cmd_get_hw_info_pasid(self->device_id, &max_pasid); + ASSERT_EQ(0, max_pasid); + if (variant->pasid_capable) { +-- +2.51.0 + diff --git a/queue-6.12/iommufd-selftest-update-hw_info-coverage-for-an-inpu.patch b/queue-6.12/iommufd-selftest-update-hw_info-coverage-for-an-inpu.patch new file mode 100644 index 0000000000..03ae3a57f1 --- /dev/null +++ b/queue-6.12/iommufd-selftest-update-hw_info-coverage-for-an-inpu.patch @@ -0,0 +1,178 @@ +From de34aee69f711f64029e423284bf055c7aa6100f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 22:59:14 -0700 +Subject: iommufd/selftest: Update hw_info coverage for an input data_type + +From: Nicolin Chen + +[ Upstream commit 3a35f7d4a4673edf6f02422bb2d78b17c667e167 ] + +Test both IOMMU_HW_INFO_TYPE_DEFAULT and IOMMU_HW_INFO_TYPE_SELFTEST, and +add a negative test for an unsupported type. + +Also drop the unused mask in test_cmd_get_hw_capabilities() as checkpatch +is complaining. + +Link: https://patch.msgid.link/r/f01a1e50cd7366f217cbf192ad0b2b79e0eb89f0.1752126748.git.nicolinc@nvidia.com +Signed-off-by: Nicolin Chen +Reviewed-by: Pranjal Shrivastava +Signed-off-by: Jason Gunthorpe +Stable-dep-of: 5b244b077c0b ("iommufd/selftest: Make it clearer to gcc that the access is not out of bounds") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/iommu/iommufd.c | 32 +++++++++++++----- + .../selftests/iommu/iommufd_fail_nth.c | 4 +-- + tools/testing/selftests/iommu/iommufd_utils.h | 33 +++++++++++-------- + 3 files changed, 46 insertions(+), 23 deletions(-) + +diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c +index 92c6020c15fa1..b678b24f5a142 100644 +--- a/tools/testing/selftests/iommu/iommufd.c ++++ b/tools/testing/selftests/iommu/iommufd.c +@@ -614,19 +614,34 @@ TEST_F(iommufd_ioas, get_hw_info) + uint8_t max_pasid = 0; + + /* Provide a zero-size user_buffer */ +- test_cmd_get_hw_info(self->device_id, NULL, 0); ++ test_cmd_get_hw_info(self->device_id, ++ IOMMU_HW_INFO_TYPE_DEFAULT, NULL, 0); + /* Provide a user_buffer with exact size */ +- test_cmd_get_hw_info(self->device_id, &buffer_exact, sizeof(buffer_exact)); ++ test_cmd_get_hw_info(self->device_id, ++ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact, ++ sizeof(buffer_exact)); ++ ++ /* Request for a wrong data_type, and a correct one */ ++ test_err_get_hw_info(EOPNOTSUPP, self->device_id, ++ IOMMU_HW_INFO_TYPE_SELFTEST + 1, ++ &buffer_exact, sizeof(buffer_exact)); ++ test_cmd_get_hw_info(self->device_id, ++ IOMMU_HW_INFO_TYPE_SELFTEST, &buffer_exact, ++ sizeof(buffer_exact)); + /* + * Provide a user_buffer with size larger than the exact size to check if + * kernel zero the trailing bytes. + */ +- test_cmd_get_hw_info(self->device_id, &buffer_larger, sizeof(buffer_larger)); ++ test_cmd_get_hw_info(self->device_id, ++ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_larger, ++ sizeof(buffer_larger)); + /* + * Provide a user_buffer with size smaller than the exact size to check if + * the fields within the size range still gets updated. + */ +- test_cmd_get_hw_info(self->device_id, &buffer_smaller, sizeof(buffer_smaller)); ++ test_cmd_get_hw_info(self->device_id, ++ IOMMU_HW_INFO_TYPE_DEFAULT, ++ &buffer_smaller, sizeof(buffer_smaller)); + test_cmd_get_hw_info_pasid(self->device_id, &max_pasid); + ASSERT_EQ(0, max_pasid); + if (variant->pasid_capable) { +@@ -636,9 +651,11 @@ TEST_F(iommufd_ioas, get_hw_info) + } + } else { + test_err_get_hw_info(ENOENT, self->device_id, +- &buffer_exact, sizeof(buffer_exact)); ++ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact, ++ sizeof(buffer_exact)); + test_err_get_hw_info(ENOENT, self->device_id, +- &buffer_larger, sizeof(buffer_larger)); ++ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_larger, ++ sizeof(buffer_larger)); + } + } + +@@ -1945,8 +1962,7 @@ TEST_F(iommufd_dirty_tracking, device_dirty_capability) + + test_cmd_hwpt_alloc(self->idev_id, self->ioas_id, 0, &hwpt_id); + test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL); +- test_cmd_get_hw_capabilities(self->idev_id, caps, +- IOMMU_HW_CAP_DIRTY_TRACKING); ++ test_cmd_get_hw_capabilities(self->idev_id, caps); + ASSERT_EQ(IOMMU_HW_CAP_DIRTY_TRACKING, + caps & IOMMU_HW_CAP_DIRTY_TRACKING); + +diff --git a/tools/testing/selftests/iommu/iommufd_fail_nth.c b/tools/testing/selftests/iommu/iommufd_fail_nth.c +index 62d02556b34cc..e2012d128e11b 100644 +--- a/tools/testing/selftests/iommu/iommufd_fail_nth.c ++++ b/tools/testing/selftests/iommu/iommufd_fail_nth.c +@@ -612,8 +612,8 @@ TEST_FAIL_NTH(basic_fail_nth, device) + &idev_id)) + return -1; + +- if (_test_cmd_get_hw_info(self->fd, idev_id, &info, +- sizeof(info), NULL, NULL)) ++ if (_test_cmd_get_hw_info(self->fd, idev_id, IOMMU_HW_INFO_TYPE_DEFAULT, ++ &info, sizeof(info), NULL, NULL)) + return -1; + + if (_test_cmd_hwpt_alloc(self->fd, idev_id, ioas_id, 0, 0, &hwpt_id, +diff --git a/tools/testing/selftests/iommu/iommufd_utils.h b/tools/testing/selftests/iommu/iommufd_utils.h +index 8994b43e86f89..9668f2268bd9b 100644 +--- a/tools/testing/selftests/iommu/iommufd_utils.h ++++ b/tools/testing/selftests/iommu/iommufd_utils.h +@@ -637,20 +637,24 @@ static void teardown_iommufd(int fd, struct __test_metadata *_metadata) + #endif + + /* @data can be NULL */ +-static int _test_cmd_get_hw_info(int fd, __u32 device_id, void *data, +- size_t data_len, uint32_t *capabilities, +- uint8_t *max_pasid) ++static int _test_cmd_get_hw_info(int fd, __u32 device_id, __u32 data_type, ++ void *data, size_t data_len, ++ uint32_t *capabilities, uint8_t *max_pasid) + { + struct iommu_test_hw_info *info = (struct iommu_test_hw_info *)data; + struct iommu_hw_info cmd = { + .size = sizeof(cmd), + .dev_id = device_id, + .data_len = data_len, ++ .in_data_type = data_type, + .data_uptr = (uint64_t)data, + .out_capabilities = 0, + }; + int ret; + ++ if (data_type != IOMMU_HW_INFO_TYPE_DEFAULT) ++ cmd.flags |= IOMMU_HW_INFO_FLAG_INPUT_TYPE; ++ + ret = ioctl(fd, IOMMU_GET_HW_INFO, &cmd); + if (ret) + return ret; +@@ -693,20 +697,23 @@ static int _test_cmd_get_hw_info(int fd, __u32 device_id, void *data, + return 0; + } + +-#define test_cmd_get_hw_info(device_id, data, data_len) \ +- ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, data, \ +- data_len, NULL, NULL)) ++#define test_cmd_get_hw_info(device_id, data_type, data, data_len) \ ++ ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, data_type, \ ++ data, data_len, NULL, NULL)) + +-#define test_err_get_hw_info(_errno, device_id, data, data_len) \ +- EXPECT_ERRNO(_errno, _test_cmd_get_hw_info(self->fd, device_id, data, \ +- data_len, NULL, NULL)) ++#define test_err_get_hw_info(_errno, device_id, data_type, data, data_len) \ ++ EXPECT_ERRNO(_errno, \ ++ _test_cmd_get_hw_info(self->fd, device_id, data_type, \ ++ data, data_len, NULL, NULL)) + +-#define test_cmd_get_hw_capabilities(device_id, caps, mask) \ +- ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, NULL, \ ++#define test_cmd_get_hw_capabilities(device_id, caps) \ ++ ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, \ ++ IOMMU_HW_INFO_TYPE_DEFAULT, NULL, \ + 0, &caps, NULL)) + +-#define test_cmd_get_hw_info_pasid(device_id, max_pasid) \ +- ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, NULL, \ ++#define test_cmd_get_hw_info_pasid(device_id, max_pasid) \ ++ ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, \ ++ IOMMU_HW_INFO_TYPE_DEFAULT, NULL, \ + 0, NULL, max_pasid)) + + static int _test_ioctl_fault_alloc(int fd, __u32 *fault_id, __u32 *fault_fd) +-- +2.51.0 + diff --git a/queue-6.12/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch b/queue-6.12/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch new file mode 100644 index 0000000000..d4516a92e0 --- /dev/null +++ b/queue-6.12/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch @@ -0,0 +1,48 @@ +From 40be980713835badc2675f8c83f8828f5c4c57a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 13:39:03 +0300 +Subject: ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() + +From: Dmitry Skorodumov + +[ Upstream commit 0c57ff008a11f24f7f05fa760222692a00465fec ] + +Packets with pkt_type == PACKET_LOOPBACK are captured by +handle_frame() function, but they don't have L2 header. +We should not process them in handle_mode_l2(). + +This doesn't affect old L2 functionality, since handling +was anyway incorrect. + +Handle them the same way as in br_handle_frame(): +just pass the skb. + +To observe invalid behaviour, just start "ping -b" on bcast address +of port-interface. + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Signed-off-by: Dmitry Skorodumov +Link: https://patch.msgid.link/20251202103906.4087675-1-skorodumov.dmitry@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index ca62188a317ad..83bd65a227709 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -737,6 +737,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + ++ if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) ++ return RX_HANDLER_PASS; ++ + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.12/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch b/queue-6.12/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch new file mode 100644 index 0000000000..3c4cb61f72 --- /dev/null +++ b/queue-6.12/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch @@ -0,0 +1,80 @@ +From a9d09bd70996685b921ee05347c8d118e5db8e89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 16:52:13 +0800 +Subject: ipvs: fix ipv4 null-ptr-deref in route error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Slavin Liu + +[ Upstream commit ad891bb3d079a46a821bf2b8867854645191bab0 ] + +The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure() +without ensuring skb->dev is set, leading to a NULL pointer dereference +in fib_compute_spec_dst() when ipv4_link_failure() attempts to send +ICMP destination unreachable messages. + +The issue emerged after commit ed0de45a1008 ("ipv4: recompile ip options +in ipv4_link_failure") started calling __ip_options_compile() from +ipv4_link_failure(). This code path eventually calls fib_compute_spec_dst() +which dereferences skb->dev. An attempt was made to fix the NULL skb->dev +dereference in commit 0113d9c9d1cc ("ipv4: fix null-deref in +ipv4_link_failure"), but it only addressed the immediate dev_net(skb->dev) +dereference by using a fallback device. The fix was incomplete because +fib_compute_spec_dst() later in the call chain still accesses skb->dev +directly, which remains NULL when IPVS calls dst_link_failure(). + +The crash occurs when: +1. IPVS processes a packet in NAT mode with a misconfigured destination +2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route +3. The error path calls dst_link_failure(skb) with skb->dev == NULL +4. ipv4_link_failure() → ipv4_send_dest_unreach() → + __ip_options_compile() → fib_compute_spec_dst() +5. fib_compute_spec_dst() dereferences NULL skb->dev + +Apply the same fix used for IPv6 in commit 326bf17ea5d4 ("ipvs: fix +ipv6 route unreach panic"): set skb->dev from skb_dst(skb)->dev before +calling dst_link_failure(). + +KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f] +CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2 +RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233 +RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285 +Call Trace: + + spec_dst_fill net/ipv4/ip_options.c:232 + spec_dst_fill net/ipv4/ip_options.c:229 + __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330 + ipv4_send_dest_unreach net/ipv4/route.c:1252 + ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265 + dst_link_failure include/net/dst.h:437 + __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412 + ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764 + +Fixes: ed0de45a1008 ("ipv4: recompile ip options in ipv4_link_failure") +Signed-off-by: Slavin Liu +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/ipvs/ip_vs_xmit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 014f077403695..fa2db17f6298b 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -409,6 +409,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + return -1; + + err_unreach: ++ if (!skb->dev) ++ skb->dev = skb_dst(skb)->dev; ++ + dst_link_failure(skb); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.12/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch b/queue-6.12/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch new file mode 100644 index 0000000000..73b3674192 --- /dev/null +++ b/queue-6.12/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch @@ -0,0 +1,96 @@ +From ce1810f4776af91f8b7063538c62d701fb2a25e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:13 +0100 +Subject: mlxsw: spectrum_mr: Fix use-after-free when updating multicast route + stats + +From: Ido Schimmel + +[ Upstream commit 8ac1dacec458f55f871f7153242ed6ab60373b90 ] + +Cited commit added a dedicated mutex (instead of RTNL) to protect the +multicast route list, so that it will not change while the driver +periodically traverses it in order to update the kernel about multicast +route stats that were queried from the device. + +One instance of list entry deletion (during route replace) was missed +and it can result in a use-after-free [1]. + +Fix by acquiring the mutex before deleting the entry from the list and +releasing it afterwards. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] +Read of size 8 at addr ffff8881523c2fa8 by task kworker/2:5/22043 + +CPU: 2 UID: 0 PID: 22043 Comm: kworker/2:5 Not tainted 6.18.0-rc1-custom-g1a3d6d7cd014 #1 PREEMPT(full) +Hardware name: Mellanox Technologies Ltd. MSN2010/SA002610, BIOS 5.6.5 08/24/2017 +Workqueue: mlxsw_core mlxsw_sp_mr_stats_update [mlxsw_spectrum] +Call Trace: + + dump_stack_lvl+0xba/0x110 + print_report+0x174/0x4f5 + kasan_report+0xdf/0x110 + mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + mlxsw_sp_mr_route_add+0xd8/0x4770 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x43/0x70 + kfree+0x14e/0x700 + mlxsw_sp_mr_route_add+0x2dea/0x4770 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:444 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Fixes: f38656d06725 ("mlxsw: spectrum_mr: Protect multicast route list with a lock") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/f996feecfd59fde297964bfc85040b6d83ec6089.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +index 5afe6b155ef0d..81935f87bfcd7 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table, + rhashtable_remove_fast(&mr_table->route_ht, + &mr_orig_route->ht_node, + mlxsw_sp_mr_route_ht_params); ++ mutex_lock(&mr_table->route_list_lock); + list_del(&mr_orig_route->node); ++ mutex_unlock(&mr_table->route_list_lock); + mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); + } + +-- +2.51.0 + diff --git a/queue-6.12/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch b/queue-6.12/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch new file mode 100644 index 0000000000..ee53ac0ffb --- /dev/null +++ b/queue-6.12/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch @@ -0,0 +1,199 @@ +From a8f8fa19957625e4c93787b8126a2f159259ce03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:12 +0100 +Subject: mlxsw: spectrum_router: Fix neighbour use-after-free + +From: Ido Schimmel + +[ Upstream commit 8b0e69763ef948fb872a7767df4be665d18f5fd4 ] + +We sometimes observe use-after-free when dereferencing a neighbour [1]. +The problem seems to be that the driver stores a pointer to the +neighbour, but without holding a reference on it. A reference is only +taken when the neighbour is used by a nexthop. + +Fix by simplifying the reference counting scheme. Always take a +reference when storing a neighbour pointer in a neighbour entry. Avoid +taking a referencing when the neighbour is used by a nexthop as the +neighbour entry associated with the nexthop already holds a reference. + +Tested by running the test that uncovered the problem over 300 times. +Without this patch the problem was reproduced after a handful of +iterations. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_neigh_entry_update+0x2d4/0x310 +Read of size 8 at addr ffff88817f8e3420 by task ip/3929 + +CPU: 3 UID: 0 PID: 3929 Comm: ip Not tainted 6.18.0-rc4-virtme-g36b21a067510 #3 PREEMPT(full) +Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 +Call Trace: + + dump_stack_lvl+0x6f/0xa0 + print_address_description.constprop.0+0x6e/0x300 + print_report+0xfc/0x1fb + kasan_report+0xe4/0x110 + mlxsw_sp_neigh_entry_update+0x2d4/0x310 + mlxsw_sp_router_rif_gone_sync+0x35f/0x510 + mlxsw_sp_rif_destroy+0x1ea/0x730 + mlxsw_sp_inetaddr_port_vlan_event+0xa1/0x1b0 + __mlxsw_sp_inetaddr_lag_event+0xcc/0x130 + __mlxsw_sp_inetaddr_event+0xf5/0x3c0 + mlxsw_sp_router_netdevice_event+0x1015/0x1580 + notifier_call_chain+0xcc/0x150 + call_netdevice_notifiers_info+0x7e/0x100 + __netdev_upper_dev_unlink+0x10b/0x210 + netdev_upper_dev_unlink+0x79/0xa0 + vrf_del_slave+0x18/0x50 + do_set_master+0x146/0x7d0 + do_setlink.isra.0+0x9a0/0x2880 + rtnl_newlink+0x637/0xb20 + rtnetlink_rcv_msg+0x6fe/0xb90 + netlink_rcv_skb+0x123/0x380 + netlink_unicast+0x4a3/0x770 + netlink_sendmsg+0x75b/0xc90 + __sock_sendmsg+0xbe/0x160 + ____sys_sendmsg+0x5b2/0x7d0 + ___sys_sendmsg+0xfd/0x180 + __sys_sendmsg+0x124/0x1c0 + do_syscall_64+0xbb/0xfd0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[...] + +Allocated by task 109: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7b/0x90 + __kmalloc_noprof+0x2c1/0x790 + neigh_alloc+0x6af/0x8f0 + ___neigh_create+0x63/0xe90 + mlxsw_sp_nexthop_neigh_init+0x430/0x7e0 + mlxsw_sp_nexthop_type_init+0x212/0x960 + mlxsw_sp_nexthop6_group_info_init.constprop.0+0x81f/0x1280 + mlxsw_sp_nexthop6_group_get+0x392/0x6a0 + mlxsw_sp_fib6_entry_create+0x46a/0xfd0 + mlxsw_sp_router_fib6_replace+0x1ed/0x5f0 + mlxsw_sp_router_fib6_event_work+0x10a/0x2a0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Freed by task 154: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kmem_cache_free_bulk.part.0+0x1eb/0x5e0 + kvfree_rcu_bulk+0x1f2/0x260 + kfree_rcu_work+0x130/0x1b0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Last potentially related work creation: + kasan_save_stack+0x30/0x50 + kasan_record_aux_stack+0x8c/0xa0 + kvfree_call_rcu+0x93/0x5b0 + mlxsw_sp_router_neigh_event_work+0x67d/0x860 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Fixes: 6cf3c971dc84 ("mlxsw: spectrum_router: Add private neigh table") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/92d75e21d95d163a41b5cea67a15cd33f547cba6.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlxsw/spectrum_router.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index 4ab58cb1ab7f4..7066bc5612c62 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2265,6 +2265,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + if (!neigh_entry) + return NULL; + ++ neigh_hold(n); + neigh_entry->key.n = n; + neigh_entry->rif = rif; + INIT_LIST_HEAD(&neigh_entry->nexthop_list); +@@ -2274,6 +2275,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + + static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) + { ++ neigh_release(neigh_entry->key.n); + kfree(neigh_entry); + } + +@@ -4320,6 +4322,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + if (err) + goto err_neigh_entry_insert; + ++ neigh_release(old_n); ++ + read_lock_bh(&n->lock); + nud_state = n->nud_state; + dead = n->dead; +@@ -4328,14 +4332,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + + list_for_each_entry(nh, &neigh_entry->nexthop_list, + neigh_list_node) { +- neigh_release(old_n); +- neigh_clone(n); + __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + } + +- neigh_release(n); +- + return 0; + + err_neigh_entry_insert: +@@ -4428,6 +4428,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, + } + } + ++ /* Release the reference taken by neigh_lookup() / neigh_create() since ++ * neigh_entry already holds one. ++ */ ++ neigh_release(n); ++ + /* If that is the first nexthop connected to that neigh, add to + * nexthop_neighs_list + */ +@@ -4454,11 +4459,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) + { + struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; +- struct neighbour *n; + + if (!neigh_entry) + return; +- n = neigh_entry->key.n; + + __mlxsw_sp_nexthop_neigh_update(nh, true); + list_del(&nh->neigh_list_node); +@@ -4472,8 +4475,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + + if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) + mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); +- +- neigh_release(n); + } + + static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) +-- +2.51.0 + diff --git a/queue-6.12/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch b/queue-6.12/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch new file mode 100644 index 0000000000..e29b6da0e9 --- /dev/null +++ b/queue-6.12/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch @@ -0,0 +1,64 @@ +From f06623b857938159c3ae6c5fb717dc4553902d1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:11 +0100 +Subject: mlxsw: spectrum_router: Fix possible neighbour reference count leak + +From: Ido Schimmel + +[ Upstream commit b6b638bda240395dff49a87403b2e32493e56d2a ] + +mlxsw_sp_router_schedule_work() takes a reference on a neighbour, +expecting a work item to release it later on. However, we might fail to +schedule the work item, in which case the neighbour reference count will +be leaked. + +Fix by taking the reference just before scheduling the work item. Note +that mlxsw_sp_router_schedule_work() can receive a NULL neighbour +pointer, but neigh_clone() handles that correctly. + +Spotted during code review, did not actually observe the reference count +leak. + +Fixes: 151b89f6025a ("mlxsw: spectrum_router: Reuse work neighbor initialization in work scheduler") +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/ec2934ae4aca187a8d8c9329a08ce93cca411378.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index 511cd92e0e3e7..4ab58cb1ab7f4 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2858,6 +2858,11 @@ static int mlxsw_sp_router_schedule_work(struct net *net, + if (!net_work) + return NOTIFY_BAD; + ++ /* Take a reference to ensure the neighbour won't be destructed until ++ * we drop the reference in the work item. ++ */ ++ neigh_clone(n); ++ + INIT_WORK(&net_work->work, cb); + net_work->mlxsw_sp = router->mlxsw_sp; + net_work->n = n; +@@ -2881,11 +2886,6 @@ static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router, + struct net *net; + + net = neigh_parms_net(n->parms); +- +- /* Take a reference to ensure the neighbour won't be destructed until we +- * drop the reference in delayed work. +- */ +- neigh_clone(n); + return mlxsw_sp_router_schedule_work(net, router, n, + mlxsw_sp_router_neigh_event_work); + } +-- +2.51.0 + diff --git a/queue-6.12/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch b/queue-6.12/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch new file mode 100644 index 0000000000..f445f6376c --- /dev/null +++ b/queue-6.12/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch @@ -0,0 +1,66 @@ +From e84a22410907b49b35165ec3f207b7812851bbcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:09:19 +0800 +Subject: net: enetc: do not transmit redirected XDP frames when the link is + down + +From: Wei Fang + +[ Upstream commit 2939203ffee818f1e5ebd60bbb85a174d63aab9c ] + +In the current implementation, the enetc_xdp_xmit() always transmits +redirected XDP frames even if the link is down, but the frames cannot +be transmitted from TX BD rings when the link is down, so the frames +are still kept in the TX BD rings. If the XDP program is uninstalled, +users will see the following warning logs. + +fsl_enetc 0000:00:00.0 eno0: timeout for tx ring #6 clear + +More worse, the TX BD ring cannot work properly anymore, because the +HW PIR and CIR are not equal after the re-initialization of the TX +BD ring. At this point, the BDs between CIR and PIR are invalid, +which will cause a hardware malfunction. + +Another reason is that there is internal context in the ring prefetch +logic that will retain the state from the first incarnation of the ring +and continue prefetching from the stale location when we re-initialize +the ring. The internal context is only reset by an FLR. That is to say, +for LS1028A ENETC, software cannot set the HW CIR and PIR when +initializing the TX BD ring. + +It does not make sense to transmit redirected XDP frames when the link is +down. Add a link status check to prevent transmission in this condition. +This fixes part of the issue, but more complex cases remain. For example, +the TX BD ring may still contain unsent frames when the link goes down. +Those situations require additional patches, which will build on this +one. + +Fixes: 9d2b68cc108d ("net: enetc: add support for XDP_REDIRECT") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Reviewed-by: Hariprasad Kelam +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20251211020919.121113-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 749b65aab14a9..c58e44144c2fa 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1429,7 +1429,8 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames, + int xdp_tx_bd_cnt, i, k; + int xdp_tx_frm_cnt = 0; + +- if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags))) ++ if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags) || ++ !netif_carrier_ok(ndev))) + return -ENETDOWN; + + enetc_lock_mdio(); +-- +2.51.0 + diff --git a/queue-6.12/net-fec-err007885-workaround-for-xdp-tx-path.patch b/queue-6.12/net-fec-err007885-workaround-for-xdp-tx-path.patch new file mode 100644 index 0000000000..6bbd873455 --- /dev/null +++ b/queue-6.12/net-fec-err007885-workaround-for-xdp-tx-path.patch @@ -0,0 +1,49 @@ +From 506822590d2945c06a0964c27cff7af163b76bc3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:59:15 +0800 +Subject: net: fec: ERR007885 Workaround for XDP TX path + +From: Wei Fang + +[ Upstream commit e8e032cd24dda7cceaa27bc2eb627f82843f0466 ] + +The ERR007885 will lead to a TDAR race condition for mutliQ when the +driver sets TDAR and the UDMA clears TDAR simultaneously or in a small +window (2-4 cycles). And it will cause the udma_tx and udma_tx_arbiter +state machines to hang. Therefore, the commit 53bb20d1faba ("net: fec: +add variable reg_desc_active to speed things up") and the commit +a179aad12bad ("net: fec: ERR007885 Workaround for conventional TX") have +added the workaround to fix the potential issue for the conventional TX +path. Similarly, the XDP TX path should also have the potential hang +issue, so add the workaround for XDP TX path. + +Fixes: 6d6b39f180b8 ("net: fec: add initial XDP support") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251128025915.2486943-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index d1800868c2e01..9018a7d3864fd 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -3934,7 +3934,12 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, + txq->bd.cur = bdp; + + /* Trigger transmission start */ +- writel(0, txq->bd.reg_desc_active); ++ if (!(fep->quirks & FEC_QUIRK_ERR007885) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active)) ++ writel(0, txq->bd.reg_desc_active); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.12/net-handshake-duplicate-handshake-cancellations-leak.patch b/queue-6.12/net-handshake-duplicate-handshake-cancellations-leak.patch new file mode 100644 index 0000000000..f5c78ca45e --- /dev/null +++ b/queue-6.12/net-handshake-duplicate-handshake-cancellations-leak.patch @@ -0,0 +1,61 @@ +From ea2a1609f958d628aa9d8af8201c7d63d182b0c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:30:15 -0500 +Subject: net/handshake: duplicate handshake cancellations leak socket + +From: Scott Mayhew + +[ Upstream commit 15564bd67e2975002f2a8e9defee33e321d3183f ] + +When a handshake request is cancelled it is removed from the +handshake_net->hn_requests list, but it is still present in the +handshake_rhashtbl until it is destroyed. + +If a second cancellation request arrives for the same handshake request, +then remove_pending() will return false... and assuming +HANDSHAKE_F_REQ_COMPLETED isn't set in req->hr_flags, we'll continue +processing through the out_true label, where we put another reference on +the sock and a refcount underflow occurs. + +This can happen for example if a handshake times out - particularly if +the SUNRPC client sends the AUTH_TLS probe to the server but doesn't +follow it up with the ClientHello due to a problem with tlshd. When the +timeout is hit on the server, the server will send a FIN, which triggers +a cancellation request via xs_reset_transport(). When the timeout is +hit on the client, another cancellation request happens via +xs_tls_handshake_sync(). + +Add a test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED) in the pending cancel +path so duplicate cancels can be detected. + +Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests") +Suggested-by: Chuck Lever +Signed-off-by: Scott Mayhew +Reviewed-by: Chuck Lever +Link: https://patch.msgid.link/20251209193015.3032058-1-smayhew@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/handshake/request.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/handshake/request.c b/net/handshake/request.c +index 94d5cef3e048b..0ac126b0add60 100644 +--- a/net/handshake/request.c ++++ b/net/handshake/request.c +@@ -325,7 +325,11 @@ bool handshake_req_cancel(struct sock *sk) + + hn = handshake_pernet(net); + if (hn && remove_pending(hn, req)) { +- /* Request hadn't been accepted */ ++ /* Request hadn't been accepted - mark cancelled */ ++ if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { ++ trace_handshake_cancel_busy(net, req, sk); ++ return false; ++ } + goto out_true; + } + if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { +-- +2.51.0 + diff --git a/queue-6.12/net-hns3-add-vlan-id-validation-before-using.patch b/queue-6.12/net-hns3-add-vlan-id-validation-before-using.patch new file mode 100644 index 0000000000..d60896a23a --- /dev/null +++ b/queue-6.12/net-hns3-add-vlan-id-validation-before-using.patch @@ -0,0 +1,46 @@ +From 1a875571cb7f3402dc7b81227801e6c5d06c67f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:37 +0800 +Subject: net: hns3: add VLAN id validation before using + +From: Jian Shen + +[ Upstream commit 6ef935e65902bfed53980ad2754b06a284ea8ac1 ] + +Currently, the VLAN id may be used without validation when +receive a VLAN configuration mailbox from VF. The length of +vlan_del_fail_bmap is BITS_TO_LONGS(VLAN_N_VID). It may cause +out-of-bounds memory access once the VLAN id is bigger than +or equal to VLAN_N_VID. + +Therefore, VLAN id needs to be checked to ensure it is within +the range of VLAN_N_VID. + +Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index f5eafd1ded413..8dd970ef02ac6 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -10572,6 +10572,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, + bool writen_to_tbl = false; + int ret = 0; + ++ if (vlan_id >= VLAN_N_VID) ++ return -EINVAL; ++ + /* When device is resetting or reset failed, firmware is unable to + * handle mailbox. Just record the vlan id, and remove it after + * reset finished. +-- +2.51.0 + diff --git a/queue-6.12/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch b/queue-6.12/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch new file mode 100644 index 0000000000..9452c9613c --- /dev/null +++ b/queue-6.12/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch @@ -0,0 +1,52 @@ +From 6ecf3e5c670791dcd49fe516ebd73460a21adc9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:35 +0800 +Subject: net: hns3: using the num_tqps in the vf driver to apply for resources + +From: Jian Shen + +[ Upstream commit c2a16269742e176fccdd0ef9c016a233491a49ad ] + +Currently, hdev->htqp is allocated using hdev->num_tqps, and kinfo->tqp +is allocated using kinfo->num_tqps. However, kinfo->num_tqps is set to +min(new_tqps, hdev->num_tqps); Therefore, kinfo->num_tqps may be smaller +than hdev->num_tqps, which causes some hdev->htqp[i] to remain +uninitialized in hclgevf_knic_setup(). + +Thus, this patch allocates hdev->htqp and kinfo->tqp using hdev->num_tqps, +ensuring that the lengths of hdev->htqp and kinfo->tqp are consistent +and that all elements are properly initialized. + +Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-2-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index e8573358309ca..0bf8fc7e6b3a8 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -370,12 +370,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) + new_tqps = kinfo->rss_size * num_tc; + kinfo->num_tqps = min(new_tqps, hdev->num_tqps); + +- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, ++ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, + sizeof(struct hnae3_queue *), GFP_KERNEL); + if (!kinfo->tqp) + return -ENOMEM; + +- for (i = 0; i < kinfo->num_tqps; i++) { ++ for (i = 0; i < hdev->num_tqps; i++) { + hdev->htqp[i].q.handle = &hdev->nic; + hdev->htqp[i].q.tqp_index = i; + kinfo->tqp[i] = &hdev->htqp[i].q; +-- +2.51.0 + diff --git a/queue-6.12/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch b/queue-6.12/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch new file mode 100644 index 0000000000..e8951a0900 --- /dev/null +++ b/queue-6.12/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch @@ -0,0 +1,49 @@ +From 20409cbc8c679d8e796b64b59f1b8e12354c5495 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:36 +0800 +Subject: net: hns3: using the num_tqps to check whether tqp_index is out of + range when vf get ring info from mbx + +From: Jian Shen + +[ Upstream commit d180c11aa8a6fa735f9ac2c72c61364a9afc2ba7 ] + +Currently, rss_size = num_tqps / tc_num. If tc_num is 1, then num_tqps +equals rss_size. However, if the tc_num is greater than 1, then rss_size +will be less than num_tqps, causing the tqp_index check for subsequent TCs +using rss_size to always fail. + +This patch uses the num_tqps to check whether tqp_index is out of range, +instead of rss_size. + +Fixes: 326334aad024 ("net: hns3: add a check for tqp_index in hclge_get_ring_chain_from_mbx()") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-3-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index 59c863306657f..9eab095d784bd 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx( + return -EINVAL; + + for (i = 0; i < ring_num; i++) { +- if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { ++ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { + dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", + req->msg.param[i].tqp_index, +- vport->nic.kinfo.rss_size - 1U); ++ vport->nic.kinfo.num_tqps - 1U); + return -EINVAL; + } + } +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch b/queue-6.12/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch new file mode 100644 index 0000000000..b932f0110d --- /dev/null +++ b/queue-6.12/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch @@ -0,0 +1,38 @@ +From 71c42033fff70434d0d68d060cdb98337da109d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:10 +0200 +Subject: net/mlx5: Drain firmware reset in shutdown callback + +From: Moshe Shemesh + +[ Upstream commit 5846a365fc6476b02d6766963cf0985520f0385f ] + +Invoke drain_fw_reset() in the shutdown callback to ensure all +firmware reset handling is completed before shutdown proceeds. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 11d8739b9497a..e97b3494b9161 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -2196,6 +2196,7 @@ static void shutdown(struct pci_dev *pdev) + + mlx5_core_info(dev, "Shutdown was called\n"); + set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); ++ mlx5_drain_fw_reset(dev); + mlx5_drain_health_wq(dev); + err = mlx5_try_fast_unload(dev); + if (err) +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch b/queue-6.12/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch new file mode 100644 index 0000000000..28a7a7ee59 --- /dev/null +++ b/queue-6.12/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch @@ -0,0 +1,45 @@ +From c7158c6b50d6ed840fe7f40e96afe9862b9eb0bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:09 +0200 +Subject: net/mlx5: fw reset, clear reset requested on drain_fw_reset + +From: Moshe Shemesh + +[ Upstream commit 89a898d63f6f588acf5c104c65c94a38b68c69a6 ] + +drain_fw_reset() waits for ongoing firmware reset events and blocks new +event handling, but does not clear the reset requested flag, and may +keep sync reset polling. + +To fix it, call mlx5_sync_reset_clear_reset_requested() to clear the +flag, stop sync reset polling, and resume health polling, ensuring +health issues are still detected after the firmware reset drain. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 35d2fe08c0fb5..ad4d17a243de9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -832,7 +832,8 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev) + cancel_work_sync(&fw_reset->reset_reload_work); + cancel_work_sync(&fw_reset->reset_now_work); + cancel_work_sync(&fw_reset->reset_abort_work); +- cancel_delayed_work(&fw_reset->reset_timeout_work); ++ if (test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) ++ mlx5_sync_reset_clear_reset_requested(dev, true); + } + + static const struct devlink_param mlx5_fw_reset_devlink_params[] = { +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch b/queue-6.12/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch new file mode 100644 index 0000000000..71168b809e --- /dev/null +++ b/queue-6.12/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch @@ -0,0 +1,84 @@ +From 67e8d2d9ae70078b98bfbf912f8d1f95cbfc9145 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:12 +0200 +Subject: net/mlx5: fw_tracer, Handle escaped percent properly + +From: Shay Drory + +[ Upstream commit c0289f67f7d6a0dfba0e92cfe661a5c70c8c6e92 ] + +The firmware tracer's format string validation and parameter counting +did not properly handle escaped percent signs (%%). This caused +fw_tracer to count more parameters when trace format strings contained +literal percent characters. + +To fix it, allow %% to pass string validation and skip %% sequences when +counting parameters since they represent literal percent signs rather +than format specifiers. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reported-by: Breno Leitao +Reviewed-by: Moshe Shemesh +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 9c86c8c72d049..0b82a6a133d6c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -368,11 +368,11 @@ static bool mlx5_is_valid_spec(const char *str) + while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') + str++; + +- /* Check if it's a valid integer/hex specifier: ++ /* Check if it's a valid integer/hex specifier or %%: + * Valid formats: %x, %d, %i, %u, etc. + */ + if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && +- *str != 'u' && *str != 'c') ++ *str != 'u' && *str != 'c' && *str != '%') + return false; + + return true; +@@ -390,7 +390,11 @@ static bool mlx5_tracer_validate_params(const char *str) + if (!mlx5_is_valid_spec(substr + 1)) + return false; + +- substr = strstr(substr + 1, PARAM_CHAR); ++ if (*(substr + 1) == '%') ++ substr = strstr(substr + 2, PARAM_CHAR); ++ else ++ substr = strstr(substr + 1, PARAM_CHAR); ++ + } + + return true; +@@ -469,11 +473,15 @@ static int mlx5_tracer_get_num_of_params(char *str) + substr = strstr(pstr, VAL_PARM); + } + +- /* count all the % characters */ ++ /* count all the % characters, but skip %% (escaped percent) */ + substr = strstr(str, PARAM_CHAR); + while (substr) { +- num_of_params += 1; +- str = substr + 1; ++ if (*(substr + 1) != '%') { ++ num_of_params += 1; ++ str = substr + 1; ++ } else { ++ str = substr + 2; ++ } + substr = strstr(str, PARAM_CHAR); + } + +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5-fw_tracer-validate-format-string-parameters.patch b/queue-6.12/net-mlx5-fw_tracer-validate-format-string-parameters.patch new file mode 100644 index 0000000000..039ffdae4b --- /dev/null +++ b/queue-6.12/net-mlx5-fw_tracer-validate-format-string-parameters.patch @@ -0,0 +1,195 @@ +From bf7c13751aab5ab3d9d3f31a9e8c0d945d295177 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:11 +0200 +Subject: net/mlx5: fw_tracer, Validate format string parameters + +From: Shay Drory + +[ Upstream commit b35966042d20b14e2d83330049f77deec5229749 ] + +Add validation for format string parameters in the firmware tracer to +prevent potential security vulnerabilities and crashes from malformed +format strings received from firmware. + +The firmware tracer receives format strings from the device firmware and +uses them to format trace messages. Without proper validation, bad +firmware could provide format strings with invalid format specifiers +(e.g., %s, %p, %n) that could lead to crashes, or other undefined +behavior. + +Add mlx5_tracer_validate_params() to validate that all format specifiers +in trace strings are limited to safe integer/hex formats (%x, %d, %i, +%u, %llx, %lx, etc.). Reject strings containing other format types that +could be used to access arbitrary memory or cause crashes. +Invalid format strings are added to the trace output for visibility with +"BAD_FORMAT: " prefix. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Reported-by: Breno Leitao +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 83 ++++++++++++++++--- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 74 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 080e7eab52c7e..9c86c8c72d049 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -33,6 +33,7 @@ + #include "lib/eq.h" + #include "fw_tracer.h" + #include "fw_tracer_tracepoint.h" ++#include + + static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) + { +@@ -358,6 +359,43 @@ static const char *VAL_PARM = "%llx"; + static const char *REPLACE_64_VAL_PARM = "%x%x"; + static const char *PARAM_CHAR = "%"; + ++static bool mlx5_is_valid_spec(const char *str) ++{ ++ /* Parse format specifiers to find the actual type. ++ * Structure: %[flags][width][.precision][length]type ++ * Skip flags, width, precision & length. ++ */ ++ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') ++ str++; ++ ++ /* Check if it's a valid integer/hex specifier: ++ * Valid formats: %x, %d, %i, %u, etc. ++ */ ++ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && ++ *str != 'u' && *str != 'c') ++ return false; ++ ++ return true; ++} ++ ++static bool mlx5_tracer_validate_params(const char *str) ++{ ++ const char *substr = str; ++ ++ if (!str) ++ return false; ++ ++ substr = strstr(substr, PARAM_CHAR); ++ while (substr) { ++ if (!mlx5_is_valid_spec(substr + 1)) ++ return false; ++ ++ substr = strstr(substr + 1, PARAM_CHAR); ++ } ++ ++ return true; ++} ++ + static int mlx5_tracer_message_hash(u32 message_id) + { + return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); +@@ -419,6 +457,10 @@ static int mlx5_tracer_get_num_of_params(char *str) + char *substr, *pstr = str; + int num_of_params = 0; + ++ /* Validate that all parameters are valid before processing */ ++ if (!mlx5_tracer_validate_params(str)) ++ return -EINVAL; ++ + /* replace %llx with %x%x */ + substr = strstr(pstr, VAL_PARM); + while (substr) { +@@ -570,14 +612,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + { + char tmp[512]; + +- snprintf(tmp, sizeof(tmp), str_frmt->string, +- str_frmt->params[0], +- str_frmt->params[1], +- str_frmt->params[2], +- str_frmt->params[3], +- str_frmt->params[4], +- str_frmt->params[5], +- str_frmt->params[6]); ++ if (str_frmt->invalid_string) ++ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string); ++ else ++ snprintf(tmp, sizeof(tmp), str_frmt->string, ++ str_frmt->params[0], ++ str_frmt->params[1], ++ str_frmt->params[2], ++ str_frmt->params[3], ++ str_frmt->params[4], ++ str_frmt->params[5], ++ str_frmt->params[6]); + + trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, + str_frmt->event_id, tmp); +@@ -609,6 +654,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, + return 0; + } + ++static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_string_format *cur_string) ++{ ++ cur_string->invalid_string = true; ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -619,12 +671,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + +- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); +- cur_string->last_param_num = 0; + cur_string->event_id = tracer_event->event_id; + cur_string->tmsn = tracer_event->string_event.tmsn; + cur_string->timestamp = tracer_event->string_event.timestamp; + cur_string->lost = tracer_event->lost_event; ++ cur_string->last_param_num = 0; ++ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s Invalid format string parameters\n", ++ __func__); ++ mlx5_tracer_handle_bad_format_string(tracer, cur_string); ++ return 0; ++ } + if (cur_string->num_of_params == 0) /* trace with no params */ + list_add_tail(&cur_string->list, &tracer->ready_strings_list); + } else { +@@ -634,6 +692,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + __func__, tracer_event->string_event.tmsn); + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s string parameter of invalid string, dumping\n", ++ __func__); ++ return 0; ++ } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { + pr_debug("%s Number of params exceeds the max (%d)\n", +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 5c548bb74f07b..30d0bcba88479 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -125,6 +125,7 @@ struct tracer_string_format { + struct list_head list; + u32 timestamp; + bool lost; ++ bool invalid_string; + }; + + enum mlx5_fw_tracer_ownership_state { +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5-serialize-firmware-reset-with-devlink.patch b/queue-6.12/net-mlx5-serialize-firmware-reset-with-devlink.patch new file mode 100644 index 0000000000..532ba82d20 --- /dev/null +++ b/queue-6.12/net-mlx5-serialize-firmware-reset-with-devlink.patch @@ -0,0 +1,209 @@ +From e56b4dc58eb05d61c510bef1146cc72b15aeb3db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:13 +0200 +Subject: net/mlx5: Serialize firmware reset with devlink + +From: Shay Drory + +[ Upstream commit 367e501f8b095eca08d2eb0ba4ccea5b5e82c169 ] + +The firmware reset mechanism can be triggered by asynchronous events, +which may race with other devlink operations like devlink reload or +devlink dev eswitch set, potentially leading to inconsistent states. + +This patch addresses the race by using the devl_lock to serialize the +firmware reset against other devlink operations. When a reset is +requested, the driver attempts to acquire the lock. If successful, it +sets a flag to block devlink reload or eswitch changes, ACKs the reset +to firmware and then releases the lock. If the lock is already held by +another operation, the driver NACKs the firmware reset request, +indicating that the reset cannot proceed. + +Firmware reset does not keep the devl_lock and instead uses an internal +firmware reset bit. This is because firmware resets can be triggered by +asynchronous events, and processed in different threads. It is illegal +and unsafe to acquire a lock in one thread and attempt to release it in +another, as lock ownership is intrinsically thread-specific. + +This change ensures that firmware resets and other devlink operations +are mutually exclusive during the critical reset request phase, +preventing race conditions. + +Fixes: 38b9f903f22b ("net/mlx5: Handle sync reset request event") +Signed-off-by: Shay Drory +Reviewed-by: Mateusz Berezecki +Reviewed-by: Moshe Shemesh +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/devlink.c | 5 +++ + .../mellanox/mlx5/core/eswitch_offloads.c | 6 +++ + .../ethernet/mellanox/mlx5/core/fw_reset.c | 45 +++++++++++++++++-- + .../ethernet/mellanox/mlx5/core/fw_reset.h | 1 + + 4 files changed, 53 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 511b3ba245420..e9d49afc31db5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -143,6 +143,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, + struct pci_dev *pdev = dev->pdev; + int ret = 0; + ++ if (mlx5_fw_reset_in_progress(dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Can't reload during firmware reset"); ++ return -EBUSY; ++ } ++ + if (mlx5_dev_is_lightweight(dev)) { + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 558962423521c..f4cb3e78d0651 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -52,6 +52,7 @@ + #include "devlink.h" + #include "lag/lag.h" + #include "en/tc/post_meter.h" ++#include "fw_reset.h" + + /* There are two match-all miss flows, one for unicast dst mac and + * one for multicast. +@@ -3731,6 +3732,11 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, + if (IS_ERR(esw)) + return PTR_ERR(esw); + ++ if (mlx5_fw_reset_in_progress(esw->dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Can't change eswitch mode during firmware reset"); ++ return -EBUSY; ++ } ++ + if (esw_mode_from_devlink(mode, &mlx5_mode)) + return -EINVAL; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index ad4d17a243de9..1411513da66b2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -15,6 +15,7 @@ enum { + MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, + MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, + MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, ++ MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, + }; + + struct mlx5_fw_reset { +@@ -126,6 +127,16 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty + return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL); + } + ++bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev) ++{ ++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ ++ if (!fw_reset) ++ return false; ++ ++ return test_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); ++} ++ + static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev, + u8 *reset_method) + { +@@ -241,6 +252,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); + devl_unlock(devlink); + } ++ ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + } + + static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) +@@ -456,27 +469,48 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, + reset_request_work); + struct mlx5_core_dev *dev = fw_reset->dev; ++ bool nack_request = false; ++ struct devlink *devlink; + int err; + + err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method); +- if (err) ++ if (err) { ++ nack_request = true; + mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err); ++ } else if (!mlx5_is_reset_now_capable(dev, fw_reset->reset_method) || ++ test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, ++ &fw_reset->reset_flags)) { ++ nack_request = true; ++ } + +- if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || +- !mlx5_is_reset_now_capable(dev, fw_reset->reset_method)) { ++ devlink = priv_to_devlink(dev); ++ /* For external resets, try to acquire devl_lock. Skip if devlink reset is ++ * pending (lock already held) ++ */ ++ if (nack_request || ++ (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, ++ &fw_reset->reset_flags) && ++ !devl_trylock(devlink))) { + err = mlx5_fw_reset_set_reset_sync_nack(dev); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", + err ? "Failed" : "Sent"); + return; + } ++ + if (mlx5_sync_reset_set_reset_requested(dev)) +- return; ++ goto unlock; ++ ++ set_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + + err = mlx5_fw_reset_set_reset_sync_ack(dev); + if (err) + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err); + else + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n"); ++ ++unlock: ++ if (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) ++ devl_unlock(devlink); + } + + static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id) +@@ -710,6 +744,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work) + + if (mlx5_sync_reset_clear_reset_requested(dev, true)) + return; ++ ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); + } + +@@ -746,6 +782,7 @@ static void mlx5_sync_reset_timeout_work(struct work_struct *work) + + if (mlx5_sync_reset_clear_reset_requested(dev, true)) + return; ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Timeout.\n"); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +index d5b28525c960d..2d96b2adc1cdf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +@@ -10,6 +10,7 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty + int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, + struct netlink_ext_ack *extack); + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); ++bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev); + + int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); + void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); +-- +2.51.0 + diff --git a/queue-6.12/net-openvswitch-fix-middle-attribute-validation-in-p.patch b/queue-6.12/net-openvswitch-fix-middle-attribute-validation-in-p.patch new file mode 100644 index 0000000000..e13156eb70 --- /dev/null +++ b/queue-6.12/net-openvswitch-fix-middle-attribute-validation-in-p.patch @@ -0,0 +1,112 @@ +From ccb574c6b9f4a8cbbb1aa0805337b59220b666bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:53:32 +0100 +Subject: net: openvswitch: fix middle attribute validation in push_nsh() + action + +From: Ilya Maximets + +[ Upstream commit 5ace7ef87f059d68b5f50837ef3e8a1a4870c36e ] + +The push_nsh() action structure looks like this: + + OVS_ACTION_ATTR_PUSH_NSH(OVS_KEY_ATTR_NSH(OVS_NSH_KEY_ATTR_BASE,...)) + +The outermost OVS_ACTION_ATTR_PUSH_NSH attribute is OK'ed by the +nla_for_each_nested() inside __ovs_nla_copy_actions(). The innermost +OVS_NSH_KEY_ATTR_BASE/MD1/MD2 are OK'ed by the nla_for_each_nested() +inside nsh_key_put_from_nlattr(). But nothing checks if the attribute +in the middle is OK. We don't even check that this attribute is the +OVS_KEY_ATTR_NSH. We just do a double unwrap with a pair of nla_data() +calls - first time directly while calling validate_push_nsh() and the +second time as part of the nla_for_each_nested() macro, which isn't +safe, potentially causing invalid memory access if the size of this +attribute is incorrect. The failure may not be noticed during +validation due to larger netlink buffer, but cause trouble later during +action execution where the buffer is allocated exactly to the size: + + BUG: KASAN: slab-out-of-bounds in nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + Read of size 184 at addr ffff88816459a634 by task a.out/22624 + + CPU: 8 UID: 0 PID: 22624 6.18.0-rc7+ #115 PREEMPT(voluntary) + Call Trace: + + dump_stack_lvl+0x51/0x70 + print_address_description.constprop.0+0x2c/0x390 + kasan_report+0xdd/0x110 + kasan_check_range+0x35/0x1b0 + __asan_memcpy+0x20/0x60 + nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + push_nsh+0x82/0x120 [openvswitch] + do_execute_actions+0x1405/0x2840 [openvswitch] + ovs_execute_actions+0xd5/0x3b0 [openvswitch] + ovs_packet_cmd_execute+0x949/0xdb0 [openvswitch] + genl_family_rcv_msg_doit+0x1d6/0x2b0 + genl_family_rcv_msg+0x336/0x580 + genl_rcv_msg+0x9f/0x130 + netlink_rcv_skb+0x11f/0x370 + genl_rcv+0x24/0x40 + netlink_unicast+0x73e/0xaa0 + netlink_sendmsg+0x744/0xbf0 + __sys_sendto+0x3d6/0x450 + do_syscall_64+0x79/0x2c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + +Let's add some checks that the attribute is properly sized and it's +the only one attribute inside the action. Technically, there is no +real reason for OVS_KEY_ATTR_NSH to be there, as we know that we're +pushing an NSH header already, it just creates extra nesting, but +that's how uAPI works today. So, keeping as it is. + +Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") +Reported-by: Junvy Yang +Signed-off-by: Ilya Maximets +Acked-by: Eelco Chaudron echaudro@redhat.com +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20251204105334.900379-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index e3359e15aa2e4..7d5490ea23e1d 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2802,13 +2802,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, + return err; + } + +-static bool validate_push_nsh(const struct nlattr *attr, bool log) ++static bool validate_push_nsh(const struct nlattr *a, bool log) + { ++ struct nlattr *nsh_key = nla_data(a); + struct sw_flow_match match; + struct sw_flow_key key; + ++ /* There must be one and only one NSH header. */ ++ if (!nla_ok(nsh_key, nla_len(a)) || ++ nla_total_size(nla_len(nsh_key)) != nla_len(a) || ++ nla_type(nsh_key) != OVS_KEY_ATTR_NSH) ++ return false; ++ + ovs_match_init(&match, &key, true, NULL); +- return !nsh_key_put_from_nlattr(attr, &match, false, true, log); ++ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log); + } + + /* Return false if there are any non-masked bits set. +@@ -3388,7 +3395,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, + return -EINVAL; + } + mac_proto = MAC_PROTO_NONE; +- if (!validate_push_nsh(nla_data(a), log)) ++ if (!validate_push_nsh(a, log)) + return -EINVAL; + break; + +-- +2.51.0 + diff --git a/queue-6.12/net-sched-ets-always-remove-class-from-active-list-b.patch b/queue-6.12/net-sched-ets-always-remove-class-from-active-list-b.patch new file mode 100644 index 0000000000..13e4526b27 --- /dev/null +++ b/queue-6.12/net-sched-ets-always-remove-class-from-active-list-b.patch @@ -0,0 +1,232 @@ +From a773822336c3ab6fb0511a016ccc156376ca33e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: net/sched: ets: Always remove class from active list before deleting + in ets_qdisc_change + +From: Jamal Hadi Salim + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 82635dd2cfa59..ae46643e596d3 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -652,7 +652,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.51.0 + diff --git a/queue-6.12/net-sched-ets-remove-drr-class-from-the-active-list-.patch b/queue-6.12/net-sched-ets-remove-drr-class-from-the-active-list-.patch new file mode 100644 index 0000000000..08a04fc833 --- /dev/null +++ b/queue-6.12/net-sched-ets-remove-drr-class-from-the-active-list-.patch @@ -0,0 +1,88 @@ +From 5657b91dc6d2b8fdf094060a9185ceead654078a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:01:24 -0300 +Subject: net/sched: ets: Remove drr class from the active list if it changes + to strict + +From: Victor Nogueira + +[ Upstream commit b1e125ae425aba9b45252e933ca8df52a843ec70 ] + +Whenever a user issues an ets qdisc change command, transforming a +drr class into a strict one, the ets code isn't checking whether that +class was in the active list and removing it. This means that, if a +user changes a strict class (which was in the active list) back to a drr +one, that class will be added twice to the active list [1]. + +Doing so with the following commands: + +tc qdisc add dev lo root handle 1: ets bands 2 strict 1 +tc qdisc add dev lo parent 1:2 handle 20: \ + tbf rate 8bit burst 100b latency 1s +tc filter add dev lo parent 1: basic classid 1:2 +ping -c1 -W0.01 -s 56 127.0.0.1 +tc qdisc change dev lo root handle 1: ets bands 2 strict 2 +tc qdisc change dev lo root handle 1: ets bands 2 strict 1 +ping -c1 -W0.01 -s 56 127.0.0.1 + +Will trigger the following splat with list debug turned on: + +[ 59.279014][ T365] ------------[ cut here ]------------ +[ 59.279452][ T365] list_add double add: new=ffff88801d60e350, prev=ffff88801d60e350, next=ffff88801d60e2c0. +[ 59.280153][ T365] WARNING: CPU: 3 PID: 365 at lib/list_debug.c:35 __list_add_valid_or_report+0x17f/0x220 +[ 59.280860][ T365] Modules linked in: +[ 59.281165][ T365] CPU: 3 UID: 0 PID: 365 Comm: tc Not tainted 6.18.0-rc7-00105-g7e9f13163c13-dirty #239 PREEMPT(voluntary) +[ 59.281977][ T365] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 59.282391][ T365] RIP: 0010:__list_add_valid_or_report+0x17f/0x220 +[ 59.282842][ T365] Code: 89 c6 e8 d4 b7 0d ff 90 0f 0b 90 90 31 c0 e9 31 ff ff ff 90 48 c7 c7 e0 a0 22 9f 48 89 f2 48 89 c1 4c 89 c6 e8 b2 b7 0d ff 90 <0f> 0b 90 90 31 c0 e9 0f ff ff ff 48 89 f7 48 89 44 24 10 4c 89 44 +... +[ 59.288812][ T365] Call Trace: +[ 59.289056][ T365] +[ 59.289224][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.289546][ T365] ets_qdisc_change+0xd2b/0x1e80 +[ 59.289891][ T365] ? __lock_acquire+0x7e7/0x1be0 +[ 59.290223][ T365] ? __pfx_ets_qdisc_change+0x10/0x10 +[ 59.290546][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.290898][ T365] ? __mutex_trylock_common+0xda/0x240 +[ 59.291228][ T365] ? __pfx___mutex_trylock_common+0x10/0x10 +[ 59.291655][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.291993][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.292313][ T365] ? trace_contention_end+0xc8/0x110 +[ 59.292656][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293022][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293351][ T365] tc_modify_qdisc+0x63a/0x1cf0 + +Fix this by always checking and removing an ets class from the active list +when changing it to strict. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/net/sched/sch_ets.c?id=ce052b9402e461a9aded599f5b47e76bc727f7de#n663 + +Fixes: cd9b50adc6bb9 ("net/sched: ets: fix crash when flipping from 'strict' to 'quantum'") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Reviewed-by: Petr Machata +Link: https://patch.msgid.link/20251208190125.1868423-1-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index ae46643e596d3..306e046276d46 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -664,6 +664,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nstrict; i < nstrict; i++) { ++ if (cl_is_active(&q->classes[i])) ++ list_del_init(&q->classes[i].alist); ++ } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + +-- +2.51.0 + diff --git a/queue-6.12/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch b/queue-6.12/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch new file mode 100644 index 0000000000..6f6c631e4b --- /dev/null +++ b/queue-6.12/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch @@ -0,0 +1,90 @@ +From 191b042ce00604aab1491b19a9f26e88753d2239 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 12:58:01 +0100 +Subject: netfilter: nf_conncount: fix leaked ct in error paths + +From: Fernando Fernandez Mancera + +[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ] + +There are some situations where ct might be leaked as error paths are +skipping the refcounted check and return immediately. In order to solve +it make sure that the check is always called. + +Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conncount.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index b84cfb5616df4..3c1b155f7a0ea 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net, + struct nf_conn *found_ct; + unsigned int collect = 0; + bool refcounted = false; ++ int err = 0; + + if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- if (refcounted) +- nf_ct_put(ct); +- return -EEXIST; ++ err = -EEXIST; ++ goto out_put; + } + + if ((u32)jiffies == list->last_gc) +@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net, + } + + add_new_node: +- if (WARN_ON_ONCE(list->count > INT_MAX)) +- return -EOVERFLOW; ++ if (WARN_ON_ONCE(list->count > INT_MAX)) { ++ err = -EOVERFLOW; ++ goto out_put; ++ } + + conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); +- if (conn == NULL) +- return -ENOMEM; ++ if (conn == NULL) { ++ err = -ENOMEM; ++ goto out_put; ++ } + + conn->tuple = tuple; + conn->zone = *zone; +@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net, + out_put: + if (refcounted) + nf_ct_put(ct); +- return 0; ++ return err; + } + + int nf_conncount_add_skb(struct net *net, +@@ -446,11 +450,10 @@ insert_tree(struct net *net, + + rb_link_node_rcu(&rbconn->node, parent, rbnode); + rb_insert_color(&rbconn->node, root); +- +- if (refcounted) +- nf_ct_put(ct); + } + out_unlock: ++ if (refcounted) ++ nf_ct_put(ct); + spin_unlock_bh(&nf_conncount_locks[hash]); + return count; + } +-- +2.51.0 + diff --git a/queue-6.12/netfilter-nf_nat-remove-bogus-direction-check.patch b/queue-6.12/netfilter-nf_nat-remove-bogus-direction-check.patch new file mode 100644 index 0000000000..0fd70ce1cc --- /dev/null +++ b/queue-6.12/netfilter-nf_nat-remove-bogus-direction-check.patch @@ -0,0 +1,129 @@ +From d741950da7f6cc641e85d0e67a613a5d07f42f68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:00:34 +0100 +Subject: netfilter: nf_nat: remove bogus direction check + +From: Florian Westphal + +[ Upstream commit 5ec8ca26fe93103577c904644b0957f069d0051a ] + +Jakub reports spurious failures of the 'conntrack_reverse_clash.sh' +selftest. A bogus test makes nat core resort to port rewrite even +though there is no need for this. + +When the test is made, nf_nat_used_tuple() would already have caused us +to return if no other CPU had added a colliding entry. +Moreover, nf_nat_used_tuple() would have ignored the colliding entry if +their origin tuples had been the same. + +All that is left to check is if the colliding entry in the hash table +is subject to NAT, and, if its not, if our entry matches in the reverse +direction, e.g. hash table has + +addr1:1234 -> addr2:80, and we want to commit +addr2:80 -> addr1:1234. + +Because we already checked that neither the new nor the committed entry is +subject to NAT we only have to check origin vs. reply tuple: +for non-nat entries, the reply tuple is always the inverted original. + +Just in case there are more problems extend the error reporting +in the selftest while at it and dump conntrack table/stats on error. + +Reported-by: Jakub Kicinski +Closes: https://lore.kernel.org/netdev/20251206175135.4a56591b@kernel.org/ +Fixes: d8f84a9bc7c4 ("netfilter: nf_nat: don't try nat source port reallocation for reverse dir clash") +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_nat_core.c | 14 +------------- + .../net/netfilter/conntrack_reverse_clash.c | 13 +++++++++---- + .../net/netfilter/conntrack_reverse_clash.sh | 2 ++ + 3 files changed, 12 insertions(+), 17 deletions(-) + +diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c +index 02f10a46fab7c..746acd124ea28 100644 +--- a/net/netfilter/nf_nat_core.c ++++ b/net/netfilter/nf_nat_core.c +@@ -298,25 +298,13 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple, + + ct = nf_ct_tuplehash_to_ctrack(thash); + +- /* NB: IP_CT_DIR_ORIGINAL should be impossible because +- * nf_nat_used_tuple() handles origin collisions. +- * +- * Handle remote chance other CPU confirmed its ct right after. +- */ +- if (thash->tuple.dst.dir != IP_CT_DIR_REPLY) +- goto out; +- + /* clashing connection subject to NAT? Retry with new tuple. */ + if (READ_ONCE(ct->status) & uses_nat) + goto out; + + if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, +- &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple) && +- nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, +- &ignored_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) { ++ &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple)) + taken = false; +- goto out; +- } + out: + nf_ct_put(ct); + return taken; +diff --git a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c +index 507930cee8cb6..462d628cc3bdb 100644 +--- a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c ++++ b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c +@@ -33,9 +33,14 @@ static void die(const char *e) + exit(111); + } + +-static void die_port(uint16_t got, uint16_t want) ++static void die_port(const struct sockaddr_in *sin, uint16_t want) + { +- fprintf(stderr, "Port number changed, wanted %d got %d\n", want, ntohs(got)); ++ uint16_t got = ntohs(sin->sin_port); ++ char str[INET_ADDRSTRLEN]; ++ ++ inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)); ++ ++ fprintf(stderr, "Port number changed, wanted %d got %d from %s\n", want, got, str); + exit(1); + } + +@@ -100,7 +105,7 @@ int main(int argc, char *argv[]) + die("child recvfrom"); + + if (peer.sin_port != htons(PORT)) +- die_port(peer.sin_port, PORT); ++ die_port(&peer, PORT); + } else { + if (sendto(s2, buf, LEN, 0, (struct sockaddr *)&sa1, sizeof(sa1)) != LEN) + continue; +@@ -109,7 +114,7 @@ int main(int argc, char *argv[]) + die("parent recvfrom"); + + if (peer.sin_port != htons((PORT + 1))) +- die_port(peer.sin_port, PORT + 1); ++ die_port(&peer, PORT + 1); + } + } + +diff --git a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh +index a24c896347a88..dc7e9d6da0624 100755 +--- a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh ++++ b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh +@@ -45,6 +45,8 @@ if ip netns exec "$ns0" ./conntrack_reverse_clash; then + echo "PASS: No SNAT performed for null bindings" + else + echo "ERROR: SNAT performed without any matching snat rule" ++ ip netns exec "$ns0" conntrack -L ++ ip netns exec "$ns0" conntrack -S + exit 1 + fi + +-- +2.51.0 + diff --git a/queue-6.12/netfilter-nf_tables-remove-redundant-chain-validatio.patch b/queue-6.12/netfilter-nf_tables-remove-redundant-chain-validatio.patch new file mode 100644 index 0000000000..ef77c7aa17 --- /dev/null +++ b/queue-6.12/netfilter-nf_tables-remove-redundant-chain-validatio.patch @@ -0,0 +1,59 @@ +From 67493ab8c62efacf710dce88eb69412dd50ef829 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Nov 2025 13:42:05 +0100 +Subject: netfilter: nf_tables: remove redundant chain validation on register + store + +From: Pablo Neira Ayuso + +[ Upstream commit a67fd55f6a09f4119b7232c19e0f348fe31ab0db ] + +This validation predates the introduction of the state machine that +determines when to enter slow path validation for error reporting. + +Currently, table validation is perform when: + +- new rule contains expressions that need validation. +- new set element with jump/goto verdict. + +Validation on register store skips most checks with no basechains, still +this walks the graph searching for loops and ensuring expressions are +called from the right hook. Remove this. + +Fixes: a654de8fdc18 ("netfilter: nf_tables: fix chain dependency validation") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index e1c617b488889..b4741fb337988 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -11211,21 +11211,10 @@ static int nft_validate_register_store(const struct nft_ctx *ctx, + enum nft_data_types type, + unsigned int len) + { +- int err; +- + switch (reg) { + case NFT_REG_VERDICT: + if (type != NFT_DATA_VERDICT) + return -EINVAL; +- +- if (data != NULL && +- (data->verdict.code == NFT_GOTO || +- data->verdict.code == NFT_JUMP)) { +- err = nft_chain_validate(ctx, data->verdict.chain); +- if (err < 0) +- return err; +- } +- + break; + default: + if (type != NFT_DATA_VALUE) +-- +2.51.0 + diff --git a/queue-6.12/netrom-fix-memory-leak-in-nr_sendmsg.patch b/queue-6.12/netrom-fix-memory-leak-in-nr_sendmsg.patch new file mode 100644 index 0000000000..59e8c777e6 --- /dev/null +++ b/queue-6.12/netrom-fix-memory-leak-in-nr_sendmsg.patch @@ -0,0 +1,74 @@ +From 505eccb8c5767c5e1784559f032b408c455da0d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 12:13:15 +0800 +Subject: netrom: Fix memory leak in nr_sendmsg() + +From: Wang Liang + +[ Upstream commit 613d12dd794e078be8ff3cf6b62a6b9acf7f4619 ] + +syzbot reported a memory leak [1]. + +When function sock_alloc_send_skb() return NULL in nr_output(), the +original skb is not freed, which was allocated in nr_sendmsg(). Fix this +by freeing it before return. + +[1] +BUG: memory leak +unreferenced object 0xffff888129f35500 (size 240): + comm "syz.0.17", pid 6119, jiffies 4294944652 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 10 52 28 81 88 ff ff ..........R(.... + backtrace (crc 1456a3e4): + kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline] + slab_post_alloc_hook mm/slub.c:4983 [inline] + slab_alloc_node mm/slub.c:5288 [inline] + kmem_cache_alloc_node_noprof+0x36f/0x5e0 mm/slub.c:5340 + __alloc_skb+0x203/0x240 net/core/skbuff.c:660 + alloc_skb include/linux/skbuff.h:1383 [inline] + alloc_skb_with_frags+0x69/0x3f0 net/core/skbuff.c:6671 + sock_alloc_send_pskb+0x379/0x3e0 net/core/sock.c:2965 + sock_alloc_send_skb include/net/sock.h:1859 [inline] + nr_sendmsg+0x287/0x450 net/netrom/af_netrom.c:1105 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg net/socket.c:742 [inline] + sock_write_iter+0x293/0x2a0 net/socket.c:1195 + new_sync_write fs/read_write.c:593 [inline] + vfs_write+0x45d/0x710 fs/read_write.c:686 + ksys_write+0x143/0x170 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xa4/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7abc36bbbb6d7d40b58 +Tested-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20251129041315.1550766-1-wangliang74@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_out.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 5e531394a724b..2b3cbceb0b52d 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) + frontlen = skb_headroom(skb); + + while (skb->len > 0) { +- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) ++ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) { ++ kfree_skb(skb); + return; ++ } + + skb_reserve(skbn, frontlen); + +-- +2.51.0 + diff --git a/queue-6.12/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch b/queue-6.12/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch new file mode 100644 index 0000000000..f689de5617 --- /dev/null +++ b/queue-6.12/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch @@ -0,0 +1,37 @@ +From 2fba550b3985efa5a36fc53bd0bb8c14a81c943e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 09:56:39 +0300 +Subject: nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() + +From: Dan Carpenter + +[ Upstream commit 885bebac9909994050bbbeed0829c727e42bd1b7 ] + +Set the error code if "transferred != sizeof(cmd)" instead of +returning success. + +Fixes: dbafc28955fa ("NFC: pn533: don't send USB data off of the stack") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aTfIJ9tZPmeUF4W1@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c +index ffd7367ce1194..018a80674f06e 100644 +--- a/drivers/nfc/pn533/usb.c ++++ b/drivers/nfc/pn533/usb.c +@@ -406,7 +406,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) + if (rc || (transferred != sizeof(cmd))) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); +- return rc; ++ return rc ?: -EINVAL; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); +-- +2.51.0 + diff --git a/queue-6.12/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch b/queue-6.12/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch new file mode 100644 index 0000000000..71277acafe --- /dev/null +++ b/queue-6.12/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch @@ -0,0 +1,41 @@ +From c07d7adb1efa70d6d1ca503d6b94065f8fb24c5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 13:16:49 +0100 +Subject: selftests: netfilter: packetdrill: avoid failure on HZ=100 kernel + +From: Florian Westphal + +[ Upstream commit fec7b0795548b43e2c3c46e3143c34ef6070341c ] + +packetdrill --ip_version=ipv4 --mtu=1500 --tolerance_usecs=1000000 --non_fatal packet conntrack_syn_challenge_ack.pkt +conntrack v1.4.8 (conntrack-tools): 1 flow entries have been shown. +conntrack_syn_challenge_ack.pkt:32: error executing `conntrack -f $NFCT_IP_VERSION \ +-L -p tcp --dport 8080 | grep UNREPLIED | grep -q SYN_SENT` command: non-zero status 1 + +Affected kernel had CONFIG_HZ=100; reset packet was still sitting in +backlog. + +Reported-by: Yi Chen +Fixes: a8a388c2aae4 ("selftests: netfilter: add packetdrill based conntrack tests") +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + .../net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt b/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt +index 3442cd29bc932..cdb3910af95b4 100644 +--- a/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt ++++ b/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt +@@ -26,7 +26,7 @@ + + +0.01 > R 643160523:643160523(0) win 0 + +-+0.01 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT` +++0.1 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT` + + // Must go through. + +0.01 > S 0:0(0) win 65535 +-- +2.51.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 7cc312b701..0d234f2e37 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -42,3 +42,36 @@ bluetooth-btusb-mt7920-add-vid-pid-0489-e135.patch bluetooth-btusb-add-new-vid-pid-13d3-3533-for-rtl882.patch bluetooth-btusb-add-new-vid-pid-0x0489-0xe12f-for-rt.patch gfs2-fix-use-of-bio_chain.patch +net-fec-err007885-workaround-for-xdp-tx-path.patch +netrom-fix-memory-leak-in-nr_sendmsg.patch +net-sched-ets-always-remove-class-from-active-list-b.patch +ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch +mlxsw-spectrum_router-fix-possible-neighbour-referen.patch +mlxsw-spectrum_router-fix-neighbour-use-after-free.patch +mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch +bnxt_en-fix-xdp_tx-path.patch +net-openvswitch-fix-middle-attribute-validation-in-p.patch +broadcom-b44-prevent-uninitialized-value-usage.patch +netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch +ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch +caif-fix-integer-underflow-in-cffrml_receive.patch +net-sched-ets-remove-drr-class-from-the-active-list-.patch +nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch +netfilter-nf_nat-remove-bogus-direction-check.patch +netfilter-nf_tables-remove-redundant-chain-validatio.patch +selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch +iommufd-selftest-add-coverage-for-reporting-max_pasi.patch +iommufd-selftest-update-hw_info-coverage-for-an-inpu.patch +iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch +iommufd-selftest-check-for-overflow-in-iommu_test_op.patch +ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch +net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch +net-mlx5-drain-firmware-reset-in-shutdown-callback.patch +net-mlx5-fw_tracer-validate-format-string-parameters.patch +net-mlx5-fw_tracer-handle-escaped-percent-properly.patch +net-mlx5-serialize-firmware-reset-with-devlink.patch +net-handshake-duplicate-handshake-cancellations-leak.patch +net-enetc-do-not-transmit-redirected-xdp-frames-when.patch +net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch +net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch +net-hns3-add-vlan-id-validation-before-using.patch diff --git a/queue-6.18/bnxt_en-fix-xdp_tx-path.patch b/queue-6.18/bnxt_en-fix-xdp_tx-path.patch new file mode 100644 index 0000000000..b640f4e5ce --- /dev/null +++ b/queue-6.18/bnxt_en-fix-xdp_tx-path.patch @@ -0,0 +1,74 @@ +From 27f5af46c0c8a38985bc2e4633391663b3e1fad0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 16:30:24 -0800 +Subject: bnxt_en: Fix XDP_TX path + +From: Michael Chan + +[ Upstream commit 0373d5c387f24de749cc22e694a14b3a7c7eb515 ] + +For XDP_TX action in bnxt_rx_xdp(), clearing of the event flags is not +correct. __bnxt_poll_work() -> bnxt_rx_pkt() -> bnxt_rx_xdp() may be +looping within NAPI and some event flags may be set in earlier +iterations. In particular, if BNXT_TX_EVENT is set earlier indicating +some XDP_TX packets are ready and pending, it will be cleared if it is +XDP_TX action again. Normally, we will set BNXT_TX_EVENT again when we +successfully call __bnxt_xmit_xdp(). But if the TX ring has no more +room, the flag will not be set. This will cause the TX producer to be +ahead but the driver will not hit the TX doorbell. + +For multi-buf XDP_TX, there is no need to clear the event flags and set +BNXT_AGG_EVENT. The BNXT_AGG_EVENT flag should have been set earlier in +bnxt_rx_pkt(). + +The visible symptom of this is that the RX ring associated with the +TX XDP ring will eventually become empty and all packets will be dropped. +Because this condition will cause the driver to not refill the RX ring +seeing that the TX ring has forever pending XDP_TX packets. + +The fix is to only clear BNXT_RX_EVENT when we have successfully +called __bnxt_xmit_xdp(). + +Fixes: 7f0a168b0441 ("bnxt_en: Add completion ring pointer in TX and RX ring structures") +Reported-by: Pavel Dubovitsky +Reviewed-by: Andy Gospodarek +Reviewed-by: Pavan Chebbi +Reviewed-by: Kalesh AP +Signed-off-by: Michael Chan +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20251203003024.2246699-1-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +index 3e77a96e5a3e3..c94a391b1ba5b 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +@@ -268,13 +268,11 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, + case XDP_TX: + rx_buf = &rxr->rx_buf_ring[cons]; + mapping = rx_buf->mapping - bp->rx_dma_offset; +- *event &= BNXT_TX_CMP_EVENT; + + if (unlikely(xdp_buff_has_frags(xdp))) { + struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); + + tx_needed += sinfo->nr_frags; +- *event = BNXT_AGG_EVENT; + } + + if (tx_avail < tx_needed) { +@@ -287,6 +285,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, + dma_sync_single_for_device(&pdev->dev, mapping + offset, *len, + bp->rx_dir); + ++ *event &= ~BNXT_RX_EVENT; + *event |= BNXT_TX_EVENT; + __bnxt_xmit_xdp(bp, txr, mapping + offset, *len, + NEXT_RX(rxr->rx_prod), xdp); +-- +2.51.0 + diff --git a/queue-6.18/broadcom-b44-prevent-uninitialized-value-usage.patch b/queue-6.18/broadcom-b44-prevent-uninitialized-value-usage.patch new file mode 100644 index 0000000000..cca84d9dbf --- /dev/null +++ b/queue-6.18/broadcom-b44-prevent-uninitialized-value-usage.patch @@ -0,0 +1,45 @@ +From b665ba585b9a17e8c91e77884f85d45a5ec561c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 18:58:16 +0300 +Subject: broadcom: b44: prevent uninitialized value usage + +From: Alexey Simakov + +[ Upstream commit 50b3db3e11864cb4e18ff099cfb38e11e7f87a68 ] + +On execution path with raised B44_FLAG_EXTERNAL_PHY, b44_readphy() +leaves bmcr value uninitialized and it is used later in the code. + +Add check of this flag at the beginning of the b44_nway_reset() and +exit early of the function with restarting autonegotiation if an +external PHY is used. + +Fixes: 753f492093da ("[B44]: port to native ssb support") +Reviewed-by: Jonas Gorski +Reviewed-by: Andrew Lunn +Signed-off-by: Alexey Simakov +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20251205155815.4348-1-bigalex934@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/b44.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c +index 0353359c3fe96..073d7d490d4b6 100644 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -1789,6 +1789,9 @@ static int b44_nway_reset(struct net_device *dev) + u32 bmcr; + int r; + ++ if (bp->flags & B44_FLAG_EXTERNAL_PHY) ++ return phy_ethtool_nway_reset(dev); ++ + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); +-- +2.51.0 + diff --git a/queue-6.18/caif-fix-integer-underflow-in-cffrml_receive.patch b/queue-6.18/caif-fix-integer-underflow-in-cffrml_receive.patch new file mode 100644 index 0000000000..864d5209ee --- /dev/null +++ b/queue-6.18/caif-fix-integer-underflow-in-cffrml_receive.patch @@ -0,0 +1,58 @@ +From 7f401d0b83f02f589b05857ec760a920f62358ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 21:30:47 +0800 +Subject: caif: fix integer underflow in cffrml_receive() + +From: Junrui Luo + +[ Upstream commit 8a11ff0948b5ad09b71896b7ccc850625f9878d1 ] + +The cffrml_receive() function extracts a length field from the packet +header and, when FCS is disabled, subtracts 2 from this length without +validating that len >= 2. + +If an attacker sends a malicious packet with a length field of 0 or 1 +to an interface with FCS disabled, the subtraction causes an integer +underflow. + +This can lead to memory exhaustion and kernel instability, potential +information disclosure if padding contains uninitialized kernel memory. + +Fix this by validating that len >= 2 before performing the subtraction. + +Reported-by: Yuhao Jiang +Reported-by: Junrui Luo +Fixes: b482cd2053e3 ("net-caif: add CAIF core protocol stack") +Signed-off-by: Junrui Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/SYBPR01MB7881511122BAFEA8212A1608AFA6A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/caif/cffrml.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c +index 6651a8dc62e04..d4d63586053ad 100644 +--- a/net/caif/cffrml.c ++++ b/net/caif/cffrml.c +@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) + len = le16_to_cpu(tmp); + + /* Subtract for FCS on length if FCS is not used. */ +- if (!this->dofcs) ++ if (!this->dofcs) { ++ if (len < 2) { ++ ++cffrml_rcv_error; ++ pr_err("Invalid frame length (%d)\n", len); ++ cfpkt_destroy(pkt); ++ return -EPROTO; ++ } + len -= 2; ++ } + + if (cfpkt_setlen(pkt, len) < 0) { + ++cffrml_rcv_error; +-- +2.51.0 + diff --git a/queue-6.18/can-j1939-make-j1939_sk_bind-fail-if-device-is-no-lo.patch b/queue-6.18/can-j1939-make-j1939_sk_bind-fail-if-device-is-no-lo.patch new file mode 100644 index 0000000000..3ac1cbd90c --- /dev/null +++ b/queue-6.18/can-j1939-make-j1939_sk_bind-fail-if-device-is-no-lo.patch @@ -0,0 +1,54 @@ +From e006f63bc5ac902e241dcf50dbdc5a11b26202ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 22:43:12 +0900 +Subject: can: j1939: make j1939_sk_bind() fail if device is no longer + registered + +From: Tetsuo Handa + +[ Upstream commit 46cea215dc9444ec32a76b1b6a9cb809e17b64d5 ] + +There is a theoretical race window in j1939_sk_netdev_event_unregister() +where two j1939_sk_bind() calls jump in between read_unlock_bh() and +lock_sock(). + +The assumption jsk->priv == priv can fail if the first j1939_sk_bind() +call once made jsk->priv == NULL due to failed j1939_local_ecu_get() call +and the second j1939_sk_bind() call again made jsk->priv != NULL due to +successful j1939_local_ecu_get() call. + +Since the socket lock is held by both j1939_sk_netdev_event_unregister() +and j1939_sk_bind(), checking ndev->reg_state with the socket lock held can +reliably make the second j1939_sk_bind() call fail (and close this race +window). + +Fixes: 7fcbe5b2c6a4 ("can: j1939: implement NETDEV_UNREGISTER notification handler") +Signed-off-by: Tetsuo Handa +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/5732921e-247e-4957-a364-da74bd7031d7@I-love.SAKURA.ne.jp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/socket.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c +index 88e7160d42489..e3ba2e9fc0e9b 100644 +--- a/net/can/j1939/socket.c ++++ b/net/can/j1939/socket.c +@@ -482,6 +482,12 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len) + goto out_release_sock; + } + ++ if (ndev->reg_state != NETREG_REGISTERED) { ++ dev_put(ndev); ++ ret = -ENODEV; ++ goto out_release_sock; ++ } ++ + can_ml = can_get_ml_priv(ndev); + if (!can_ml) { + dev_put(ndev); +-- +2.51.0 + diff --git a/queue-6.18/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch b/queue-6.18/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch new file mode 100644 index 0000000000..6b1295ea71 --- /dev/null +++ b/queue-6.18/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch @@ -0,0 +1,159 @@ +From c409cedbeee44bebcaa6fb7e3d8cf6c080fef8d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 14:19:01 +0200 +Subject: ethtool: Avoid overflowing userspace buffer on stats query + +From: Gal Pressman + +[ Upstream commit 7b07be1ff1cb6c49869910518650e8d0abc7d25f ] + +The ethtool -S command operates across three ioctl calls: +ETHTOOL_GSSET_INFO for the size, ETHTOOL_GSTRINGS for the names, and +ETHTOOL_GSTATS for the values. + +If the number of stats changes between these calls (e.g., due to device +reconfiguration), userspace's buffer allocation will be incorrect, +potentially leading to buffer overflow. + +Drivers are generally expected to maintain stable stat counts, but some +drivers (e.g., mlx5, bnx2x, bna, ksz884x) use dynamic counters, making +this scenario possible. + +Some drivers try to handle this internally: +- bnad_get_ethtool_stats() returns early in case stats.n_stats is not + equal to the driver's stats count. +- micrel/ksz884x also makes sure not to write anything beyond + stats.n_stats and overflow the buffer. + +However, both use stats.n_stats which is already assigned with the value +returned from get_sset_count(), hence won't solve the issue described +here. + +Change ethtool_get_strings(), ethtool_get_stats(), +ethtool_get_phy_stats() to not return anything in case of a mismatch +between userspace's size and get_sset_size(), to prevent buffer +overflow. +The returned n_stats value will be equal to zero, to reflect that +nothing has been returned. + +This could result in one of two cases when using upstream ethtool, +depending on when the size change is detected: +1. When detected in ethtool_get_strings(): + # ethtool -S eth2 + no stats available + +2. When detected in get stats, all stats will be reported as zero. + +Both cases are presumably transient, and a subsequent ethtool call +should succeed. + +Other than the overflow avoidance, these two cases are very evident (no +output/cleared stats), which is arguably better than presenting +incorrect/shifted stats. +I also considered returning an error instead of a "silent" response, but +that seems more destructive towards userspace apps. + +Notes: +- This patch does not claim to fix the inherent race, it only makes sure + that we do not overflow the userspace buffer, and makes for a more + predictable behavior. + +- RTNL lock is held during each ioctl, the race window exists between + the separate ioctl calls when the lock is released. + +- Userspace ethtool always fills stats.n_stats, but it is likely that + these stats ioctls are implemented in other userspace applications + which might not fill it. The added code checks that it's not zero, + to prevent any regressions. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Dragos Tatulea +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Link: https://patch.msgid.link/20251208121901.3203692-1-gal@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index fa83ddade4f81..9431e305b2333 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2383,7 +2383,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + return -ENOMEM; + WARN_ON_ONCE(!ret); + +- gstrings.len = ret; ++ if (gstrings.len && gstrings.len != ret) ++ gstrings.len = 0; ++ else ++ gstrings.len = ret; + + if (gstrings.len) { + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); +@@ -2509,10 +2512,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (stats.n_stats && stats.n_stats != n_stats) ++ stats.n_stats = 0; ++ else ++ stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (stats.n_stats) { ++ data = vzalloc(array_size(stats.n_stats, sizeof(u64))); + if (!data) + return -ENOMEM; + ops->get_ethtool_stats(dev, &stats, data); +@@ -2524,7 +2530,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + goto out; + ret = 0; + +@@ -2560,6 +2568,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, + return -EOPNOTSUPP; + + n_stats = phy_ops->get_sset_count(phydev); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2580,6 +2592,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev, + return -EOPNOTSUPP; + + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2616,7 +2632,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + } + + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + ret = -EFAULT; + + out: +-- +2.51.0 + diff --git a/queue-6.18/inet-frags-add-inet_frag_queue_flush.patch b/queue-6.18/inet-frags-add-inet_frag_queue_flush.patch new file mode 100644 index 0000000000..71169148e5 --- /dev/null +++ b/queue-6.18/inet-frags-add-inet_frag_queue_flush.patch @@ -0,0 +1,96 @@ +From 84aebf278962baf9f86d4b6fe4bed47aea68e42d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Dec 2025 17:09:40 -0800 +Subject: inet: frags: add inet_frag_queue_flush() + +From: Jakub Kicinski + +[ Upstream commit 1231eec6994be29d6bb5c303dfa54731ed9fc0e6 ] + +Instead of exporting inet_frag_rbtree_purge() which requires that +caller takes care of memory accounting, add a new helper. We will +need to call it from a few places in the next patch. + +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251207010942.1672972-3-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 006a5035b495 ("inet: frags: flush pending skbs in fqdir_pre_exit()") +Signed-off-by: Sasha Levin +--- + include/net/inet_frag.h | 5 ++--- + net/ipv4/inet_fragment.c | 15 ++++++++++++--- + net/ipv4/ip_fragment.c | 6 +----- + 3 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h +index 0eccd9c3a883f..3ffaceee7bbc0 100644 +--- a/include/net/inet_frag.h ++++ b/include/net/inet_frag.h +@@ -141,9 +141,8 @@ void inet_frag_kill(struct inet_frag_queue *q, int *refs); + void inet_frag_destroy(struct inet_frag_queue *q); + struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key); + +-/* Free all skbs in the queue; return the sum of their truesizes. */ +-unsigned int inet_frag_rbtree_purge(struct rb_root *root, +- enum skb_drop_reason reason); ++void inet_frag_queue_flush(struct inet_frag_queue *q, ++ enum skb_drop_reason reason); + + static inline void inet_frag_putn(struct inet_frag_queue *q, int refs) + { +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 30f4fa50ee2d7..1bf969b5a1cb5 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -263,8 +263,8 @@ static void inet_frag_destroy_rcu(struct rcu_head *head) + kmem_cache_free(f->frags_cachep, q); + } + +-unsigned int inet_frag_rbtree_purge(struct rb_root *root, +- enum skb_drop_reason reason) ++static unsigned int ++inet_frag_rbtree_purge(struct rb_root *root, enum skb_drop_reason reason) + { + struct rb_node *p = rb_first(root); + unsigned int sum = 0; +@@ -284,7 +284,16 @@ unsigned int inet_frag_rbtree_purge(struct rb_root *root, + } + return sum; + } +-EXPORT_SYMBOL(inet_frag_rbtree_purge); ++ ++void inet_frag_queue_flush(struct inet_frag_queue *q, ++ enum skb_drop_reason reason) ++{ ++ unsigned int sum; ++ ++ sum = inet_frag_rbtree_purge(&q->rb_fragments, reason); ++ sub_frag_mem_limit(q->fqdir, sum); ++} ++EXPORT_SYMBOL(inet_frag_queue_flush); + + void inet_frag_destroy(struct inet_frag_queue *q) + { +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index d7bccdc9dc693..32f1c1a46ba72 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -240,14 +240,10 @@ static int ip_frag_too_far(struct ipq *qp) + + static int ip_frag_reinit(struct ipq *qp) + { +- unsigned int sum_truesize = 0; +- + if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) + return -ETIMEDOUT; + +- sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments, +- SKB_DROP_REASON_FRAG_TOO_FAR); +- sub_frag_mem_limit(qp->q.fqdir, sum_truesize); ++ inet_frag_queue_flush(&qp->q, SKB_DROP_REASON_FRAG_TOO_FAR); + + qp->q.flags = 0; + qp->q.len = 0; +-- +2.51.0 + diff --git a/queue-6.18/inet-frags-avoid-theoretical-race-in-ip_frag_reinit.patch b/queue-6.18/inet-frags-avoid-theoretical-race-in-ip_frag_reinit.patch new file mode 100644 index 0000000000..9c3771fb45 --- /dev/null +++ b/queue-6.18/inet-frags-avoid-theoretical-race-in-ip_frag_reinit.patch @@ -0,0 +1,67 @@ +From f5ff9aa6ba0479713ff73c5bcade81d184095eb9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Dec 2025 17:09:39 -0800 +Subject: inet: frags: avoid theoretical race in ip_frag_reinit() + +From: Jakub Kicinski + +[ Upstream commit 8ef522c8a59a048117f7e05eb5213043c02f986f ] + +In ip_frag_reinit() we want to move the frag timeout timer into +the future. If the timer fires in the meantime we inadvertently +scheduled it again, and since the timer assumes a ref on frag_queue +we need to acquire one to balance things out. + +This is technically racy, we should have acquired the reference +_before_ we touch the timer, it may fire again before we take the ref. +Avoid this entire dance by using mod_timer_pending() which only modifies +the timer if its pending (and which exists since Linux v2.6.30) + +Note that this was the only place we ever took a ref on frag_queue +since Eric's conversion to RCU. So we could potentially replace +the whole refcnt field with an atomic flag and a bit more RCU. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251207010942.1672972-2-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_fragment.c | 4 +++- + net/ipv4/ip_fragment.c | 4 +--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 025895eb6ec59..30f4fa50ee2d7 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -327,7 +327,9 @@ static struct inet_frag_queue *inet_frag_alloc(struct fqdir *fqdir, + + timer_setup(&q->timer, f->frag_expire, 0); + spin_lock_init(&q->lock); +- /* One reference for the timer, one for the hash table. */ ++ /* One reference for the timer, one for the hash table. ++ * We never take any extra references, only decrement this field. ++ */ + refcount_set(&q->refcnt, 2); + + return q; +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index f7012479713ba..d7bccdc9dc693 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -242,10 +242,8 @@ static int ip_frag_reinit(struct ipq *qp) + { + unsigned int sum_truesize = 0; + +- if (!mod_timer(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) { +- refcount_inc(&qp->q.refcnt); ++ if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) + return -ETIMEDOUT; +- } + + sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments, + SKB_DROP_REASON_FRAG_TOO_FAR); +-- +2.51.0 + diff --git a/queue-6.18/inet-frags-flush-pending-skbs-in-fqdir_pre_exit.patch b/queue-6.18/inet-frags-flush-pending-skbs-in-fqdir_pre_exit.patch new file mode 100644 index 0000000000..1dbb14b9f9 --- /dev/null +++ b/queue-6.18/inet-frags-flush-pending-skbs-in-fqdir_pre_exit.patch @@ -0,0 +1,186 @@ +From 5ecc617cfb33ee1825ec7061628ad7681ebb8509 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Dec 2025 17:09:41 -0800 +Subject: inet: frags: flush pending skbs in fqdir_pre_exit() + +From: Jakub Kicinski + +[ Upstream commit 006a5035b495dec008805df249f92c22c89c3d2e ] + +We have been seeing occasional deadlocks on pernet_ops_rwsem since +September in NIPA. The stuck task was usually modprobe (often loading +a driver like ipvlan), trying to take the lock as a Writer. +lockdep does not track readers for rwsems so the read wasn't obvious +from the reports. + +On closer inspection the Reader holding the lock was conntrack looping +forever in nf_conntrack_cleanup_net_list(). Based on past experience +with occasional NIPA crashes I looked thru the tests which run before +the crash and noticed that the crash follows ip_defrag.sh. An immediate +red flag. Scouring thru (de)fragmentation queues reveals skbs sitting +around, holding conntrack references. + +The problem is that since conntrack depends on nf_defrag_ipv6, +nf_defrag_ipv6 will load first. Since nf_defrag_ipv6 loads first its +netns exit hooks run _after_ conntrack's netns exit hook. + +Flush all fragment queue SKBs during fqdir_pre_exit() to release +conntrack references before conntrack cleanup runs. Also flush +the queues in timer expiry handlers when they discover fqdir->dead +is set, in case packet sneaks in while we're running the pre_exit +flush. + +The commit under Fixes is not exactly the culprit, but I think +previously the timer firing would eventually unblock the spinning +conntrack. + +Fixes: d5dd88794a13 ("inet: fix various use-after-free in defrags units") +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251207010942.1672972-4-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/inet_frag.h | 13 +------------ + include/net/ipv6_frag.h | 9 ++++++--- + net/ipv4/inet_fragment.c | 36 ++++++++++++++++++++++++++++++++++++ + net/ipv4/ip_fragment.c | 12 +++++++----- + 4 files changed, 50 insertions(+), 20 deletions(-) + +diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h +index 3ffaceee7bbc0..365925c9d2628 100644 +--- a/include/net/inet_frag.h ++++ b/include/net/inet_frag.h +@@ -123,18 +123,7 @@ void inet_frags_fini(struct inet_frags *); + + int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net); + +-static inline void fqdir_pre_exit(struct fqdir *fqdir) +-{ +- /* Prevent creation of new frags. +- * Pairs with READ_ONCE() in inet_frag_find(). +- */ +- WRITE_ONCE(fqdir->high_thresh, 0); +- +- /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire() +- * and ip6frag_expire_frag_queue(). +- */ +- WRITE_ONCE(fqdir->dead, true); +-} ++void fqdir_pre_exit(struct fqdir *fqdir); + void fqdir_exit(struct fqdir *fqdir); + + void inet_frag_kill(struct inet_frag_queue *q, int *refs); +diff --git a/include/net/ipv6_frag.h b/include/net/ipv6_frag.h +index 38ef66826939e..41d9fc6965f9a 100644 +--- a/include/net/ipv6_frag.h ++++ b/include/net/ipv6_frag.h +@@ -69,9 +69,6 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq) + int refs = 1; + + rcu_read_lock(); +- /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */ +- if (READ_ONCE(fq->q.fqdir->dead)) +- goto out_rcu_unlock; + spin_lock(&fq->q.lock); + + if (fq->q.flags & INET_FRAG_COMPLETE) +@@ -80,6 +77,12 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq) + fq->q.flags |= INET_FRAG_DROP; + inet_frag_kill(&fq->q, &refs); + ++ /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */ ++ if (READ_ONCE(fq->q.fqdir->dead)) { ++ inet_frag_queue_flush(&fq->q, 0); ++ goto out; ++ } ++ + dev = dev_get_by_index_rcu(net, fq->iif); + if (!dev) + goto out; +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 1bf969b5a1cb5..001ee5c4d962e 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -218,6 +218,41 @@ static int __init inet_frag_wq_init(void) + + pure_initcall(inet_frag_wq_init); + ++void fqdir_pre_exit(struct fqdir *fqdir) ++{ ++ struct inet_frag_queue *fq; ++ struct rhashtable_iter hti; ++ ++ /* Prevent creation of new frags. ++ * Pairs with READ_ONCE() in inet_frag_find(). ++ */ ++ WRITE_ONCE(fqdir->high_thresh, 0); ++ ++ /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire() ++ * and ip6frag_expire_frag_queue(). ++ */ ++ WRITE_ONCE(fqdir->dead, true); ++ ++ rhashtable_walk_enter(&fqdir->rhashtable, &hti); ++ rhashtable_walk_start(&hti); ++ ++ while ((fq = rhashtable_walk_next(&hti))) { ++ if (IS_ERR(fq)) { ++ if (PTR_ERR(fq) != -EAGAIN) ++ break; ++ continue; ++ } ++ spin_lock_bh(&fq->lock); ++ if (!(fq->flags & INET_FRAG_COMPLETE)) ++ inet_frag_queue_flush(fq, 0); ++ spin_unlock_bh(&fq->lock); ++ } ++ ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++} ++EXPORT_SYMBOL(fqdir_pre_exit); ++ + void fqdir_exit(struct fqdir *fqdir) + { + INIT_WORK(&fqdir->destroy_work, fqdir_work_fn); +@@ -290,6 +325,7 @@ void inet_frag_queue_flush(struct inet_frag_queue *q, + { + unsigned int sum; + ++ reason = reason ?: SKB_DROP_REASON_FRAG_REASM_TIMEOUT; + sum = inet_frag_rbtree_purge(&q->rb_fragments, reason); + sub_frag_mem_limit(q->fqdir, sum); + } +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index 32f1c1a46ba72..56b0f738d2f27 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -134,11 +134,6 @@ static void ip_expire(struct timer_list *t) + net = qp->q.fqdir->net; + + rcu_read_lock(); +- +- /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */ +- if (READ_ONCE(qp->q.fqdir->dead)) +- goto out_rcu_unlock; +- + spin_lock(&qp->q.lock); + + if (qp->q.flags & INET_FRAG_COMPLETE) +@@ -146,6 +141,13 @@ static void ip_expire(struct timer_list *t) + + qp->q.flags |= INET_FRAG_DROP; + inet_frag_kill(&qp->q, &refs); ++ ++ /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */ ++ if (READ_ONCE(qp->q.fqdir->dead)) { ++ inet_frag_queue_flush(&qp->q, 0); ++ goto out; ++ } ++ + __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT); + +-- +2.51.0 + diff --git a/queue-6.18/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch b/queue-6.18/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch new file mode 100644 index 0000000000..72408a4339 --- /dev/null +++ b/queue-6.18/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch @@ -0,0 +1,57 @@ +From 28996d0009abf5ae7c4372a3516a44596342a881 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Dec 2025 11:53:40 -0400 +Subject: iommufd/selftest: Check for overflow in IOMMU_TEST_OP_ADD_RESERVED + +From: Jason Gunthorpe + +[ Upstream commit e6a973af11135439de32ece3b9cbe3bfc043bea8 ] + +syzkaller found it could overflow math in the test infrastructure and +cause a WARN_ON by corrupting the reserved interval tree. This only +effects test kernels with CONFIG_IOMMUFD_TEST. + +Validate the user input length in the test ioctl. + +Fixes: f4b20bb34c83 ("iommufd: Add kernel support for testing iommufd") +Link: https://patch.msgid.link/r/0-v1-cd99f6049ba5+51-iommufd_syz_add_resv_jgg@nvidia.com +Reviewed-by: Samiullah Khawaja +Reviewed-by: Kevin Tian +Tested-by: Yi Liu +Reported-by: syzbot+57fdb0cf6a0c5d1f15a2@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/69368129.a70a0220.38f243.008f.GAE@google.com +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/selftest.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c +index de178827a078a..dc0947aaac625 100644 +--- a/drivers/iommu/iommufd/selftest.c ++++ b/drivers/iommu/iommufd/selftest.c +@@ -1257,14 +1257,20 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd, + unsigned int mockpt_id, + unsigned long start, size_t length) + { ++ unsigned long last; + struct iommufd_ioas *ioas; + int rc; + ++ if (!length) ++ return -EINVAL; ++ if (check_add_overflow(start, length - 1, &last)) ++ return -EOVERFLOW; ++ + ioas = iommufd_get_ioas(ucmd->ictx, mockpt_id); + if (IS_ERR(ioas)) + return PTR_ERR(ioas); + down_write(&ioas->iopt.iova_rwsem); +- rc = iopt_reserve_iova(&ioas->iopt, start, start + length - 1, NULL); ++ rc = iopt_reserve_iova(&ioas->iopt, start, last, NULL); + up_write(&ioas->iopt.iova_rwsem); + iommufd_put_object(ucmd->ictx, &ioas->obj); + return rc; +-- +2.51.0 + diff --git a/queue-6.18/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch b/queue-6.18/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch new file mode 100644 index 0000000000..eb6105207d --- /dev/null +++ b/queue-6.18/iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch @@ -0,0 +1,71 @@ +From 0101957307e6345bc8a06191f38d9ce18f42d642 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 14:56:12 -0400 +Subject: iommufd/selftest: Make it clearer to gcc that the access is not out + of bounds + +From: Jason Gunthorpe + +[ Upstream commit 5b244b077c0b0e76573fbb9542cf038e42368901 ] + +GCC gets a bit confused and reports: + + In function '_test_cmd_get_hw_info', + inlined from 'iommufd_ioas_get_hw_info' at iommufd.c:779:3, + inlined from 'wrapper_iommufd_ioas_get_hw_info' at iommufd.c:752:1: +>> iommufd_utils.h:804:37: warning: array subscript 'struct iommu_test_hw_info[0]' is partly outside array bounds of 'struct iommu_test_hw_info_buffer_smaller[1]' [-Warray-bounds=] + 804 | assert(!info->flags); + | ~~~~^~~~~~~ + iommufd.c: In function 'wrapper_iommufd_ioas_get_hw_info': + iommufd.c:761:11: note: object 'buffer_smaller' of size 4 + 761 | } buffer_smaller; + | ^~~~~~~~~~~~~~ + +While it is true that "struct iommu_test_hw_info[0]" is partly out of +bounds of the input pointer, it is not true that info->flags is out of +bounds. Unclear why it warns on this. + +Reuse an existing properly sized stack buffer and pass a truncated length +instead to test the same thing. + +Fixes: af4fde93c319 ("iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl") +Link: https://patch.msgid.link/r/0-v1-63a2cffb09da+4486-iommufd_gcc_bounds_jgg@nvidia.com +Reviewed-by: Kevin Tian +Reviewed-by: Nicolin Chen +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202512032344.kaAcKFIM-lkp@intel.com/ +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/iommu/iommufd.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c +index bb4d33dde3c89..1f52140d9d9ee 100644 +--- a/tools/testing/selftests/iommu/iommufd.c ++++ b/tools/testing/selftests/iommu/iommufd.c +@@ -758,9 +758,6 @@ TEST_F(iommufd_ioas, get_hw_info) + struct iommu_test_hw_info info; + uint64_t trailing_bytes; + } buffer_larger; +- struct iommu_test_hw_info_buffer_smaller { +- __u32 flags; +- } buffer_smaller; + + if (self->device_id) { + uint8_t max_pasid = 0; +@@ -792,8 +789,9 @@ TEST_F(iommufd_ioas, get_hw_info) + * the fields within the size range still gets updated. + */ + test_cmd_get_hw_info(self->device_id, +- IOMMU_HW_INFO_TYPE_DEFAULT, +- &buffer_smaller, sizeof(buffer_smaller)); ++ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact, ++ offsetofend(struct iommu_test_hw_info, ++ flags)); + test_cmd_get_hw_info_pasid(self->device_id, &max_pasid); + ASSERT_EQ(0, max_pasid); + if (variant->pasid_capable) { +-- +2.51.0 + diff --git a/queue-6.18/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch b/queue-6.18/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch new file mode 100644 index 0000000000..88dfff5898 --- /dev/null +++ b/queue-6.18/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch @@ -0,0 +1,48 @@ +From ecaaf1c258cd1c7ae42d88734236dd56f844bf0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 13:39:03 +0300 +Subject: ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() + +From: Dmitry Skorodumov + +[ Upstream commit 0c57ff008a11f24f7f05fa760222692a00465fec ] + +Packets with pkt_type == PACKET_LOOPBACK are captured by +handle_frame() function, but they don't have L2 header. +We should not process them in handle_mode_l2(). + +This doesn't affect old L2 functionality, since handling +was anyway incorrect. + +Handle them the same way as in br_handle_frame(): +just pass the skb. + +To observe invalid behaviour, just start "ping -b" on bcast address +of port-interface. + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Signed-off-by: Dmitry Skorodumov +Link: https://patch.msgid.link/20251202103906.4087675-1-skorodumov.dmitry@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index d7e3ddbcab6f4..baf2ef3bcd54b 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -737,6 +737,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + ++ if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) ++ return RX_HANDLER_PASS; ++ + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.18/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch b/queue-6.18/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch new file mode 100644 index 0000000000..4799f52813 --- /dev/null +++ b/queue-6.18/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch @@ -0,0 +1,80 @@ +From 886b168d163aaa51575ef5e9c965dcdc6015f5dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 16:52:13 +0800 +Subject: ipvs: fix ipv4 null-ptr-deref in route error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Slavin Liu + +[ Upstream commit ad891bb3d079a46a821bf2b8867854645191bab0 ] + +The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure() +without ensuring skb->dev is set, leading to a NULL pointer dereference +in fib_compute_spec_dst() when ipv4_link_failure() attempts to send +ICMP destination unreachable messages. + +The issue emerged after commit ed0de45a1008 ("ipv4: recompile ip options +in ipv4_link_failure") started calling __ip_options_compile() from +ipv4_link_failure(). This code path eventually calls fib_compute_spec_dst() +which dereferences skb->dev. An attempt was made to fix the NULL skb->dev +dereference in commit 0113d9c9d1cc ("ipv4: fix null-deref in +ipv4_link_failure"), but it only addressed the immediate dev_net(skb->dev) +dereference by using a fallback device. The fix was incomplete because +fib_compute_spec_dst() later in the call chain still accesses skb->dev +directly, which remains NULL when IPVS calls dst_link_failure(). + +The crash occurs when: +1. IPVS processes a packet in NAT mode with a misconfigured destination +2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route +3. The error path calls dst_link_failure(skb) with skb->dev == NULL +4. ipv4_link_failure() → ipv4_send_dest_unreach() → + __ip_options_compile() → fib_compute_spec_dst() +5. fib_compute_spec_dst() dereferences NULL skb->dev + +Apply the same fix used for IPv6 in commit 326bf17ea5d4 ("ipvs: fix +ipv6 route unreach panic"): set skb->dev from skb_dst(skb)->dev before +calling dst_link_failure(). + +KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f] +CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2 +RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233 +RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285 +Call Trace: + + spec_dst_fill net/ipv4/ip_options.c:232 + spec_dst_fill net/ipv4/ip_options.c:229 + __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330 + ipv4_send_dest_unreach net/ipv4/route.c:1252 + ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265 + dst_link_failure include/net/dst.h:437 + __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412 + ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764 + +Fixes: ed0de45a1008 ("ipv4: recompile ip options in ipv4_link_failure") +Signed-off-by: Slavin Liu +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/ipvs/ip_vs_xmit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 95af252b29397..618fbe1240b54 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -409,6 +409,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + return -1; + + err_unreach: ++ if (!skb->dev) ++ skb->dev = skb_dst(skb)->dev; ++ + dst_link_failure(skb); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.18/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch b/queue-6.18/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch new file mode 100644 index 0000000000..eec8660b47 --- /dev/null +++ b/queue-6.18/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch @@ -0,0 +1,96 @@ +From 28b737fe91c09d4b9c5f14ff03c33dcc5659d856 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:13 +0100 +Subject: mlxsw: spectrum_mr: Fix use-after-free when updating multicast route + stats + +From: Ido Schimmel + +[ Upstream commit 8ac1dacec458f55f871f7153242ed6ab60373b90 ] + +Cited commit added a dedicated mutex (instead of RTNL) to protect the +multicast route list, so that it will not change while the driver +periodically traverses it in order to update the kernel about multicast +route stats that were queried from the device. + +One instance of list entry deletion (during route replace) was missed +and it can result in a use-after-free [1]. + +Fix by acquiring the mutex before deleting the entry from the list and +releasing it afterwards. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] +Read of size 8 at addr ffff8881523c2fa8 by task kworker/2:5/22043 + +CPU: 2 UID: 0 PID: 22043 Comm: kworker/2:5 Not tainted 6.18.0-rc1-custom-g1a3d6d7cd014 #1 PREEMPT(full) +Hardware name: Mellanox Technologies Ltd. MSN2010/SA002610, BIOS 5.6.5 08/24/2017 +Workqueue: mlxsw_core mlxsw_sp_mr_stats_update [mlxsw_spectrum] +Call Trace: + + dump_stack_lvl+0xba/0x110 + print_report+0x174/0x4f5 + kasan_report+0xdf/0x110 + mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + mlxsw_sp_mr_route_add+0xd8/0x4770 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x43/0x70 + kfree+0x14e/0x700 + mlxsw_sp_mr_route_add+0x2dea/0x4770 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:444 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Fixes: f38656d06725 ("mlxsw: spectrum_mr: Protect multicast route list with a lock") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/f996feecfd59fde297964bfc85040b6d83ec6089.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +index 5afe6b155ef0d..81935f87bfcd7 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table, + rhashtable_remove_fast(&mr_table->route_ht, + &mr_orig_route->ht_node, + mlxsw_sp_mr_route_ht_params); ++ mutex_lock(&mr_table->route_list_lock); + list_del(&mr_orig_route->node); ++ mutex_unlock(&mr_table->route_list_lock); + mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); + } + +-- +2.51.0 + diff --git a/queue-6.18/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch b/queue-6.18/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch new file mode 100644 index 0000000000..927f6f2eb7 --- /dev/null +++ b/queue-6.18/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch @@ -0,0 +1,199 @@ +From 8746306369cf5081aff8f5c7352b93221bf410f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:12 +0100 +Subject: mlxsw: spectrum_router: Fix neighbour use-after-free + +From: Ido Schimmel + +[ Upstream commit 8b0e69763ef948fb872a7767df4be665d18f5fd4 ] + +We sometimes observe use-after-free when dereferencing a neighbour [1]. +The problem seems to be that the driver stores a pointer to the +neighbour, but without holding a reference on it. A reference is only +taken when the neighbour is used by a nexthop. + +Fix by simplifying the reference counting scheme. Always take a +reference when storing a neighbour pointer in a neighbour entry. Avoid +taking a referencing when the neighbour is used by a nexthop as the +neighbour entry associated with the nexthop already holds a reference. + +Tested by running the test that uncovered the problem over 300 times. +Without this patch the problem was reproduced after a handful of +iterations. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_neigh_entry_update+0x2d4/0x310 +Read of size 8 at addr ffff88817f8e3420 by task ip/3929 + +CPU: 3 UID: 0 PID: 3929 Comm: ip Not tainted 6.18.0-rc4-virtme-g36b21a067510 #3 PREEMPT(full) +Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 +Call Trace: + + dump_stack_lvl+0x6f/0xa0 + print_address_description.constprop.0+0x6e/0x300 + print_report+0xfc/0x1fb + kasan_report+0xe4/0x110 + mlxsw_sp_neigh_entry_update+0x2d4/0x310 + mlxsw_sp_router_rif_gone_sync+0x35f/0x510 + mlxsw_sp_rif_destroy+0x1ea/0x730 + mlxsw_sp_inetaddr_port_vlan_event+0xa1/0x1b0 + __mlxsw_sp_inetaddr_lag_event+0xcc/0x130 + __mlxsw_sp_inetaddr_event+0xf5/0x3c0 + mlxsw_sp_router_netdevice_event+0x1015/0x1580 + notifier_call_chain+0xcc/0x150 + call_netdevice_notifiers_info+0x7e/0x100 + __netdev_upper_dev_unlink+0x10b/0x210 + netdev_upper_dev_unlink+0x79/0xa0 + vrf_del_slave+0x18/0x50 + do_set_master+0x146/0x7d0 + do_setlink.isra.0+0x9a0/0x2880 + rtnl_newlink+0x637/0xb20 + rtnetlink_rcv_msg+0x6fe/0xb90 + netlink_rcv_skb+0x123/0x380 + netlink_unicast+0x4a3/0x770 + netlink_sendmsg+0x75b/0xc90 + __sock_sendmsg+0xbe/0x160 + ____sys_sendmsg+0x5b2/0x7d0 + ___sys_sendmsg+0xfd/0x180 + __sys_sendmsg+0x124/0x1c0 + do_syscall_64+0xbb/0xfd0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[...] + +Allocated by task 109: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7b/0x90 + __kmalloc_noprof+0x2c1/0x790 + neigh_alloc+0x6af/0x8f0 + ___neigh_create+0x63/0xe90 + mlxsw_sp_nexthop_neigh_init+0x430/0x7e0 + mlxsw_sp_nexthop_type_init+0x212/0x960 + mlxsw_sp_nexthop6_group_info_init.constprop.0+0x81f/0x1280 + mlxsw_sp_nexthop6_group_get+0x392/0x6a0 + mlxsw_sp_fib6_entry_create+0x46a/0xfd0 + mlxsw_sp_router_fib6_replace+0x1ed/0x5f0 + mlxsw_sp_router_fib6_event_work+0x10a/0x2a0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Freed by task 154: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kmem_cache_free_bulk.part.0+0x1eb/0x5e0 + kvfree_rcu_bulk+0x1f2/0x260 + kfree_rcu_work+0x130/0x1b0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Last potentially related work creation: + kasan_save_stack+0x30/0x50 + kasan_record_aux_stack+0x8c/0xa0 + kvfree_call_rcu+0x93/0x5b0 + mlxsw_sp_router_neigh_event_work+0x67d/0x860 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Fixes: 6cf3c971dc84 ("mlxsw: spectrum_router: Add private neigh table") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/92d75e21d95d163a41b5cea67a15cd33f547cba6.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlxsw/spectrum_router.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index f4e9ecaeb104f..2d0e89bd2fb9c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2265,6 +2265,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + if (!neigh_entry) + return NULL; + ++ neigh_hold(n); + neigh_entry->key.n = n; + neigh_entry->rif = rif; + INIT_LIST_HEAD(&neigh_entry->nexthop_list); +@@ -2274,6 +2275,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + + static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) + { ++ neigh_release(neigh_entry->key.n); + kfree(neigh_entry); + } + +@@ -4320,6 +4322,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + if (err) + goto err_neigh_entry_insert; + ++ neigh_release(old_n); ++ + read_lock_bh(&n->lock); + nud_state = n->nud_state; + dead = n->dead; +@@ -4328,14 +4332,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + + list_for_each_entry(nh, &neigh_entry->nexthop_list, + neigh_list_node) { +- neigh_release(old_n); +- neigh_clone(n); + __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + } + +- neigh_release(n); +- + return 0; + + err_neigh_entry_insert: +@@ -4428,6 +4428,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, + } + } + ++ /* Release the reference taken by neigh_lookup() / neigh_create() since ++ * neigh_entry already holds one. ++ */ ++ neigh_release(n); ++ + /* If that is the first nexthop connected to that neigh, add to + * nexthop_neighs_list + */ +@@ -4454,11 +4459,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) + { + struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; +- struct neighbour *n; + + if (!neigh_entry) + return; +- n = neigh_entry->key.n; + + __mlxsw_sp_nexthop_neigh_update(nh, true); + list_del(&nh->neigh_list_node); +@@ -4472,8 +4475,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + + if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) + mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); +- +- neigh_release(n); + } + + static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) +-- +2.51.0 + diff --git a/queue-6.18/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch b/queue-6.18/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch new file mode 100644 index 0000000000..0a2e09a7f2 --- /dev/null +++ b/queue-6.18/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch @@ -0,0 +1,64 @@ +From 3bef36dd4be67e84765cf52f66eea7f18cff72c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:11 +0100 +Subject: mlxsw: spectrum_router: Fix possible neighbour reference count leak + +From: Ido Schimmel + +[ Upstream commit b6b638bda240395dff49a87403b2e32493e56d2a ] + +mlxsw_sp_router_schedule_work() takes a reference on a neighbour, +expecting a work item to release it later on. However, we might fail to +schedule the work item, in which case the neighbour reference count will +be leaked. + +Fix by taking the reference just before scheduling the work item. Note +that mlxsw_sp_router_schedule_work() can receive a NULL neighbour +pointer, but neigh_clone() handles that correctly. + +Spotted during code review, did not actually observe the reference count +leak. + +Fixes: 151b89f6025a ("mlxsw: spectrum_router: Reuse work neighbor initialization in work scheduler") +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/ec2934ae4aca187a8d8c9329a08ce93cca411378.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index a2033837182e8..f4e9ecaeb104f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2858,6 +2858,11 @@ static int mlxsw_sp_router_schedule_work(struct net *net, + if (!net_work) + return NOTIFY_BAD; + ++ /* Take a reference to ensure the neighbour won't be destructed until ++ * we drop the reference in the work item. ++ */ ++ neigh_clone(n); ++ + INIT_WORK(&net_work->work, cb); + net_work->mlxsw_sp = router->mlxsw_sp; + net_work->n = n; +@@ -2881,11 +2886,6 @@ static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router, + struct net *net; + + net = neigh_parms_net(n->parms); +- +- /* Take a reference to ensure the neighbour won't be destructed until we +- * drop the reference in delayed work. +- */ +- neigh_clone(n); + return mlxsw_sp_router_schedule_work(net, router, n, + mlxsw_sp_router_neigh_event_work); + } +-- +2.51.0 + diff --git a/queue-6.18/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch b/queue-6.18/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch new file mode 100644 index 0000000000..9f4a683e61 --- /dev/null +++ b/queue-6.18/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch @@ -0,0 +1,66 @@ +From d7d8a336443be4b64c120b55ba3313e08efbb9c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:09:19 +0800 +Subject: net: enetc: do not transmit redirected XDP frames when the link is + down + +From: Wei Fang + +[ Upstream commit 2939203ffee818f1e5ebd60bbb85a174d63aab9c ] + +In the current implementation, the enetc_xdp_xmit() always transmits +redirected XDP frames even if the link is down, but the frames cannot +be transmitted from TX BD rings when the link is down, so the frames +are still kept in the TX BD rings. If the XDP program is uninstalled, +users will see the following warning logs. + +fsl_enetc 0000:00:00.0 eno0: timeout for tx ring #6 clear + +More worse, the TX BD ring cannot work properly anymore, because the +HW PIR and CIR are not equal after the re-initialization of the TX +BD ring. At this point, the BDs between CIR and PIR are invalid, +which will cause a hardware malfunction. + +Another reason is that there is internal context in the ring prefetch +logic that will retain the state from the first incarnation of the ring +and continue prefetching from the stale location when we re-initialize +the ring. The internal context is only reset by an FLR. That is to say, +for LS1028A ENETC, software cannot set the HW CIR and PIR when +initializing the TX BD ring. + +It does not make sense to transmit redirected XDP frames when the link is +down. Add a link status check to prevent transmission in this condition. +This fixes part of the issue, but more complex cases remain. For example, +the TX BD ring may still contain unsent frames when the link goes down. +Those situations require additional patches, which will build on this +one. + +Fixes: 9d2b68cc108d ("net: enetc: add support for XDP_REDIRECT") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Reviewed-by: Hariprasad Kelam +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20251211020919.121113-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 0535e92404e3c..f410c245ea918 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1778,7 +1778,8 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames, + int xdp_tx_bd_cnt, i, k; + int xdp_tx_frm_cnt = 0; + +- if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags))) ++ if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags) || ++ !netif_carrier_ok(ndev))) + return -ENETDOWN; + + enetc_lock_mdio(); +-- +2.51.0 + diff --git a/queue-6.18/net-fec-err007885-workaround-for-xdp-tx-path.patch b/queue-6.18/net-fec-err007885-workaround-for-xdp-tx-path.patch new file mode 100644 index 0000000000..389bc06aba --- /dev/null +++ b/queue-6.18/net-fec-err007885-workaround-for-xdp-tx-path.patch @@ -0,0 +1,49 @@ +From 4faf0d7eb045ad493b1d913bec3362ef0f7036c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:59:15 +0800 +Subject: net: fec: ERR007885 Workaround for XDP TX path + +From: Wei Fang + +[ Upstream commit e8e032cd24dda7cceaa27bc2eb627f82843f0466 ] + +The ERR007885 will lead to a TDAR race condition for mutliQ when the +driver sets TDAR and the UDMA clears TDAR simultaneously or in a small +window (2-4 cycles). And it will cause the udma_tx and udma_tx_arbiter +state machines to hang. Therefore, the commit 53bb20d1faba ("net: fec: +add variable reg_desc_active to speed things up") and the commit +a179aad12bad ("net: fec: ERR007885 Workaround for conventional TX") have +added the workaround to fix the potential issue for the conventional TX +path. Similarly, the XDP TX path should also have the potential hang +issue, so add the workaround for XDP TX path. + +Fixes: 6d6b39f180b8 ("net: fec: add initial XDP support") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251128025915.2486943-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 3222359ac15b7..e2b75d1970ae6 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -3948,7 +3948,12 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, + txq->bd.cur = bdp; + + /* Trigger transmission start */ +- writel(0, txq->bd.reg_desc_active); ++ if (!(fep->quirks & FEC_QUIRK_ERR007885) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active)) ++ writel(0, txq->bd.reg_desc_active); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.18/net-handshake-duplicate-handshake-cancellations-leak.patch b/queue-6.18/net-handshake-duplicate-handshake-cancellations-leak.patch new file mode 100644 index 0000000000..da1c8db2c1 --- /dev/null +++ b/queue-6.18/net-handshake-duplicate-handshake-cancellations-leak.patch @@ -0,0 +1,61 @@ +From ab880bdf65c96fea9f7d0e061cd814f1f28703c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:30:15 -0500 +Subject: net/handshake: duplicate handshake cancellations leak socket + +From: Scott Mayhew + +[ Upstream commit 15564bd67e2975002f2a8e9defee33e321d3183f ] + +When a handshake request is cancelled it is removed from the +handshake_net->hn_requests list, but it is still present in the +handshake_rhashtbl until it is destroyed. + +If a second cancellation request arrives for the same handshake request, +then remove_pending() will return false... and assuming +HANDSHAKE_F_REQ_COMPLETED isn't set in req->hr_flags, we'll continue +processing through the out_true label, where we put another reference on +the sock and a refcount underflow occurs. + +This can happen for example if a handshake times out - particularly if +the SUNRPC client sends the AUTH_TLS probe to the server but doesn't +follow it up with the ClientHello due to a problem with tlshd. When the +timeout is hit on the server, the server will send a FIN, which triggers +a cancellation request via xs_reset_transport(). When the timeout is +hit on the client, another cancellation request happens via +xs_tls_handshake_sync(). + +Add a test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED) in the pending cancel +path so duplicate cancels can be detected. + +Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests") +Suggested-by: Chuck Lever +Signed-off-by: Scott Mayhew +Reviewed-by: Chuck Lever +Link: https://patch.msgid.link/20251209193015.3032058-1-smayhew@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/handshake/request.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/handshake/request.c b/net/handshake/request.c +index 274d2c89b6b20..f78091680bca5 100644 +--- a/net/handshake/request.c ++++ b/net/handshake/request.c +@@ -324,7 +324,11 @@ bool handshake_req_cancel(struct sock *sk) + + hn = handshake_pernet(net); + if (hn && remove_pending(hn, req)) { +- /* Request hadn't been accepted */ ++ /* Request hadn't been accepted - mark cancelled */ ++ if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { ++ trace_handshake_cancel_busy(net, req, sk); ++ return false; ++ } + goto out_true; + } + if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { +-- +2.51.0 + diff --git a/queue-6.18/net-hns3-add-vlan-id-validation-before-using.patch b/queue-6.18/net-hns3-add-vlan-id-validation-before-using.patch new file mode 100644 index 0000000000..b08b965d9c --- /dev/null +++ b/queue-6.18/net-hns3-add-vlan-id-validation-before-using.patch @@ -0,0 +1,46 @@ +From 6416028abcd2ed0e0146bb209a358522838bebbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:37 +0800 +Subject: net: hns3: add VLAN id validation before using + +From: Jian Shen + +[ Upstream commit 6ef935e65902bfed53980ad2754b06a284ea8ac1 ] + +Currently, the VLAN id may be used without validation when +receive a VLAN configuration mailbox from VF. The length of +vlan_del_fail_bmap is BITS_TO_LONGS(VLAN_N_VID). It may cause +out-of-bounds memory access once the VLAN id is bigger than +or equal to VLAN_N_VID. + +Therefore, VLAN id needs to be checked to ensure it is within +the range of VLAN_N_VID. + +Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 782bb48c9f3d7..1b103d1154da9 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -10562,6 +10562,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, + bool writen_to_tbl = false; + int ret = 0; + ++ if (vlan_id >= VLAN_N_VID) ++ return -EINVAL; ++ + /* When device is resetting or reset failed, firmware is unable to + * handle mailbox. Just record the vlan id, and remove it after + * reset finished. +-- +2.51.0 + diff --git a/queue-6.18/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch b/queue-6.18/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch new file mode 100644 index 0000000000..52d6ff0564 --- /dev/null +++ b/queue-6.18/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch @@ -0,0 +1,52 @@ +From dadff4afc50a1c65424b53c3532aba87a072a85a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:35 +0800 +Subject: net: hns3: using the num_tqps in the vf driver to apply for resources + +From: Jian Shen + +[ Upstream commit c2a16269742e176fccdd0ef9c016a233491a49ad ] + +Currently, hdev->htqp is allocated using hdev->num_tqps, and kinfo->tqp +is allocated using kinfo->num_tqps. However, kinfo->num_tqps is set to +min(new_tqps, hdev->num_tqps); Therefore, kinfo->num_tqps may be smaller +than hdev->num_tqps, which causes some hdev->htqp[i] to remain +uninitialized in hclgevf_knic_setup(). + +Thus, this patch allocates hdev->htqp and kinfo->tqp using hdev->num_tqps, +ensuring that the lengths of hdev->htqp and kinfo->tqp are consistent +and that all elements are properly initialized. + +Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-2-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 8fcf220a120d2..70327a73dee32 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -368,12 +368,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) + new_tqps = kinfo->rss_size * num_tc; + kinfo->num_tqps = min(new_tqps, hdev->num_tqps); + +- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, ++ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, + sizeof(struct hnae3_queue *), GFP_KERNEL); + if (!kinfo->tqp) + return -ENOMEM; + +- for (i = 0; i < kinfo->num_tqps; i++) { ++ for (i = 0; i < hdev->num_tqps; i++) { + hdev->htqp[i].q.handle = &hdev->nic; + hdev->htqp[i].q.tqp_index = i; + kinfo->tqp[i] = &hdev->htqp[i].q; +-- +2.51.0 + diff --git a/queue-6.18/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch b/queue-6.18/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch new file mode 100644 index 0000000000..3437eceb9c --- /dev/null +++ b/queue-6.18/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch @@ -0,0 +1,49 @@ +From a82144265416d9b6494befd37c7693a94be97ffa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:36 +0800 +Subject: net: hns3: using the num_tqps to check whether tqp_index is out of + range when vf get ring info from mbx + +From: Jian Shen + +[ Upstream commit d180c11aa8a6fa735f9ac2c72c61364a9afc2ba7 ] + +Currently, rss_size = num_tqps / tc_num. If tc_num is 1, then num_tqps +equals rss_size. However, if the tc_num is greater than 1, then rss_size +will be less than num_tqps, causing the tqp_index check for subsequent TCs +using rss_size to always fail. + +This patch uses the num_tqps to check whether tqp_index is out of range, +instead of rss_size. + +Fixes: 326334aad024 ("net: hns3: add a check for tqp_index in hclge_get_ring_chain_from_mbx()") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-3-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index c7ff12a6c0764..b7d4e06a55d40 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx( + return -EINVAL; + + for (i = 0; i < ring_num; i++) { +- if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { ++ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { + dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", + req->msg.param[i].tqp_index, +- vport->nic.kinfo.rss_size - 1U); ++ vport->nic.kinfo.num_tqps - 1U); + return -EINVAL; + } + } +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch b/queue-6.18/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch new file mode 100644 index 0000000000..836ef5d804 --- /dev/null +++ b/queue-6.18/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch @@ -0,0 +1,38 @@ +From b2c10891be1d2923665c4e0ca024862dbf5641f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:10 +0200 +Subject: net/mlx5: Drain firmware reset in shutdown callback + +From: Moshe Shemesh + +[ Upstream commit 5846a365fc6476b02d6766963cf0985520f0385f ] + +Invoke drain_fw_reset() in the shutdown callback to ensure all +firmware reset handling is completed before shutdown proceeds. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 70c156591b0ba..9e0c9e6266a47 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -2189,6 +2189,7 @@ static void shutdown(struct pci_dev *pdev) + + mlx5_core_info(dev, "Shutdown was called\n"); + set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); ++ mlx5_drain_fw_reset(dev); + mlx5_drain_health_wq(dev); + err = mlx5_try_fast_unload(dev); + if (err) +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-fix-double-unregister-of-hca_ports-componen.patch b/queue-6.18/net-mlx5-fix-double-unregister-of-hca_ports-componen.patch new file mode 100644 index 0000000000..0e2f06b300 --- /dev/null +++ b/queue-6.18/net-mlx5-fix-double-unregister-of-hca_ports-componen.patch @@ -0,0 +1,82 @@ +From 98be4d972034cd2db29bc2c0aa461adaffa52835 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 12:12:57 +0100 +Subject: net/mlx5: Fix double unregister of HCA_PORTS component + +From: Gerd Bayer + +[ Upstream commit 6a107cfe9c99a079e578a4c5eb70038101a3599f ] + +Clear hca_devcom_comp in device's private data after unregistering it in +LAG teardown. Otherwise a slightly lagging second pass through +mlx5_unload_one() might try to unregister it again and trip over +use-after-free. + +On s390 almost all PCI level recovery events trigger two passes through +mxl5_unload_one() - one through the poll_health() method and one through +mlx5_pci_err_detected() as callback from generic PCI error recovery. +While testing PCI error recovery paths with more kernel debug features +enabled, this issue reproducibly led to kernel panics with the following +call chain: + + Unable to handle kernel pointer dereference in virtual kernel address space + Failing address: 6b6b6b6b6b6b6000 TEID: 6b6b6b6b6b6b6803 ESOP-2 FSI + Fault in home space mode while using kernel ASCE. + AS:00000000705c4007 R3:0000000000000024 + Oops: 0038 ilc:3 [#1]SMP + + CPU: 14 UID: 0 PID: 156 Comm: kmcheck Kdump: loaded Not tainted + 6.18.0-20251130.rc7.git0.16131a59cab1.300.fc43.s390x+debug #1 PREEMPT + + Krnl PSW : 0404e00180000000 0000020fc86aa1dc (__lock_acquire+0x5c/0x15f0) + R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 RI:0 EA:3 + Krnl GPRS: 0000000000000000 0000020f00000001 6b6b6b6b6b6b6c33 0000000000000000 + 0000000000000000 0000000000000000 0000000000000001 0000000000000000 + 0000000000000000 0000020fca28b820 0000000000000000 0000010a1ced8100 + 0000010a1ced8100 0000020fc9775068 0000018fce14f8b8 0000018fce14f7f8 + Krnl Code: 0000020fc86aa1cc: e3b003400004 lg %r11,832 + 0000020fc86aa1d2: a7840211 brc 8,0000020fc86aa5f4 + *0000020fc86aa1d6: c09000df0b25 larl %r9,0000020fca28b820 + >0000020fc86aa1dc: d50790002000 clc 0(8,%r9),0(%r2) + 0000020fc86aa1e2: a7840209 brc 8,0000020fc86aa5f4 + 0000020fc86aa1e6: c0e001100401 larl %r14,0000020fca8aa9e8 + 0000020fc86aa1ec: c01000e25a00 larl %r1,0000020fca2f55ec + 0000020fc86aa1f2: a7eb00e8 aghi %r14,232 + + Call Trace: + __lock_acquire+0x5c/0x15f0 + lock_acquire.part.0+0xf8/0x270 + lock_acquire+0xb0/0x1b0 + down_write+0x5a/0x250 + mlx5_detach_device+0x42/0x110 [mlx5_core] + mlx5_unload_one_devl_locked+0x50/0xc0 [mlx5_core] + mlx5_unload_one+0x42/0x60 [mlx5_core] + mlx5_pci_err_detected+0x94/0x150 [mlx5_core] + zpci_event_attempt_error_recovery+0xcc/0x388 + +Fixes: 5a977b5833b7 ("net/mlx5: Lag, move devcom registration to LAG layer") +Signed-off-by: Gerd Bayer +Reviewed-by: Moshe Shemesh +Acked-by: Tariq Toukan +Link: https://patch.msgid.link/20251202-fix_lag-v1-1-59e8177ffce0@linux.ibm.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index 3db0387bf6dcb..8ec04a5f434dd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -1413,6 +1413,7 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev) + static void mlx5_lag_unregister_hca_devcom_comp(struct mlx5_core_dev *dev) + { + mlx5_devcom_unregister_component(dev->priv.hca_devcom_comp); ++ dev->priv.hca_devcom_comp = NULL; + } + + static int mlx5_lag_register_hca_devcom_comp(struct mlx5_core_dev *dev) +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch b/queue-6.18/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch new file mode 100644 index 0000000000..afd67d5a01 --- /dev/null +++ b/queue-6.18/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch @@ -0,0 +1,45 @@ +From 98f12e0f3f7b5e02bdf6a4c95b875be26c808b91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:09 +0200 +Subject: net/mlx5: fw reset, clear reset requested on drain_fw_reset + +From: Moshe Shemesh + +[ Upstream commit 89a898d63f6f588acf5c104c65c94a38b68c69a6 ] + +drain_fw_reset() waits for ongoing firmware reset events and blocks new +event handling, but does not clear the reset requested flag, and may +keep sync reset polling. + +To fix it, call mlx5_sync_reset_clear_reset_requested() to clear the +flag, stop sync reset polling, and resume health polling, ensuring +health issues are still detected after the firmware reset drain. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 89e399606877b..33df0418e5754 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -843,7 +843,8 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev) + cancel_work_sync(&fw_reset->reset_reload_work); + cancel_work_sync(&fw_reset->reset_now_work); + cancel_work_sync(&fw_reset->reset_abort_work); +- cancel_delayed_work(&fw_reset->reset_timeout_work); ++ if (test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) ++ mlx5_sync_reset_clear_reset_requested(dev, true); + } + + static const struct devlink_param mlx5_fw_reset_devlink_params[] = { +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch b/queue-6.18/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch new file mode 100644 index 0000000000..d22edea2e6 --- /dev/null +++ b/queue-6.18/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch @@ -0,0 +1,84 @@ +From c9fa15846514fe115887c756210f53e371d3a787 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:12 +0200 +Subject: net/mlx5: fw_tracer, Handle escaped percent properly + +From: Shay Drory + +[ Upstream commit c0289f67f7d6a0dfba0e92cfe661a5c70c8c6e92 ] + +The firmware tracer's format string validation and parameter counting +did not properly handle escaped percent signs (%%). This caused +fw_tracer to count more parameters when trace format strings contained +literal percent characters. + +To fix it, allow %% to pass string validation and skip %% sequences when +counting parameters since they represent literal percent signs rather +than format specifiers. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reported-by: Breno Leitao +Reviewed-by: Moshe Shemesh +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 9c86c8c72d049..0b82a6a133d6c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -368,11 +368,11 @@ static bool mlx5_is_valid_spec(const char *str) + while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') + str++; + +- /* Check if it's a valid integer/hex specifier: ++ /* Check if it's a valid integer/hex specifier or %%: + * Valid formats: %x, %d, %i, %u, etc. + */ + if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && +- *str != 'u' && *str != 'c') ++ *str != 'u' && *str != 'c' && *str != '%') + return false; + + return true; +@@ -390,7 +390,11 @@ static bool mlx5_tracer_validate_params(const char *str) + if (!mlx5_is_valid_spec(substr + 1)) + return false; + +- substr = strstr(substr + 1, PARAM_CHAR); ++ if (*(substr + 1) == '%') ++ substr = strstr(substr + 2, PARAM_CHAR); ++ else ++ substr = strstr(substr + 1, PARAM_CHAR); ++ + } + + return true; +@@ -469,11 +473,15 @@ static int mlx5_tracer_get_num_of_params(char *str) + substr = strstr(pstr, VAL_PARM); + } + +- /* count all the % characters */ ++ /* count all the % characters, but skip %% (escaped percent) */ + substr = strstr(str, PARAM_CHAR); + while (substr) { +- num_of_params += 1; +- str = substr + 1; ++ if (*(substr + 1) != '%') { ++ num_of_params += 1; ++ str = substr + 1; ++ } else { ++ str = substr + 2; ++ } + substr = strstr(str, PARAM_CHAR); + } + +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-fw_tracer-validate-format-string-parameters.patch b/queue-6.18/net-mlx5-fw_tracer-validate-format-string-parameters.patch new file mode 100644 index 0000000000..11af89ce0c --- /dev/null +++ b/queue-6.18/net-mlx5-fw_tracer-validate-format-string-parameters.patch @@ -0,0 +1,195 @@ +From 2ee514d50589b370a170f6f4d06a2a42a6777b90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:11 +0200 +Subject: net/mlx5: fw_tracer, Validate format string parameters + +From: Shay Drory + +[ Upstream commit b35966042d20b14e2d83330049f77deec5229749 ] + +Add validation for format string parameters in the firmware tracer to +prevent potential security vulnerabilities and crashes from malformed +format strings received from firmware. + +The firmware tracer receives format strings from the device firmware and +uses them to format trace messages. Without proper validation, bad +firmware could provide format strings with invalid format specifiers +(e.g., %s, %p, %n) that could lead to crashes, or other undefined +behavior. + +Add mlx5_tracer_validate_params() to validate that all format specifiers +in trace strings are limited to safe integer/hex formats (%x, %d, %i, +%u, %llx, %lx, etc.). Reject strings containing other format types that +could be used to access arbitrary memory or cause crashes. +Invalid format strings are added to the trace output for visibility with +"BAD_FORMAT: " prefix. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Reported-by: Breno Leitao +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 83 ++++++++++++++++--- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 74 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 080e7eab52c7e..9c86c8c72d049 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -33,6 +33,7 @@ + #include "lib/eq.h" + #include "fw_tracer.h" + #include "fw_tracer_tracepoint.h" ++#include + + static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) + { +@@ -358,6 +359,43 @@ static const char *VAL_PARM = "%llx"; + static const char *REPLACE_64_VAL_PARM = "%x%x"; + static const char *PARAM_CHAR = "%"; + ++static bool mlx5_is_valid_spec(const char *str) ++{ ++ /* Parse format specifiers to find the actual type. ++ * Structure: %[flags][width][.precision][length]type ++ * Skip flags, width, precision & length. ++ */ ++ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') ++ str++; ++ ++ /* Check if it's a valid integer/hex specifier: ++ * Valid formats: %x, %d, %i, %u, etc. ++ */ ++ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && ++ *str != 'u' && *str != 'c') ++ return false; ++ ++ return true; ++} ++ ++static bool mlx5_tracer_validate_params(const char *str) ++{ ++ const char *substr = str; ++ ++ if (!str) ++ return false; ++ ++ substr = strstr(substr, PARAM_CHAR); ++ while (substr) { ++ if (!mlx5_is_valid_spec(substr + 1)) ++ return false; ++ ++ substr = strstr(substr + 1, PARAM_CHAR); ++ } ++ ++ return true; ++} ++ + static int mlx5_tracer_message_hash(u32 message_id) + { + return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); +@@ -419,6 +457,10 @@ static int mlx5_tracer_get_num_of_params(char *str) + char *substr, *pstr = str; + int num_of_params = 0; + ++ /* Validate that all parameters are valid before processing */ ++ if (!mlx5_tracer_validate_params(str)) ++ return -EINVAL; ++ + /* replace %llx with %x%x */ + substr = strstr(pstr, VAL_PARM); + while (substr) { +@@ -570,14 +612,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + { + char tmp[512]; + +- snprintf(tmp, sizeof(tmp), str_frmt->string, +- str_frmt->params[0], +- str_frmt->params[1], +- str_frmt->params[2], +- str_frmt->params[3], +- str_frmt->params[4], +- str_frmt->params[5], +- str_frmt->params[6]); ++ if (str_frmt->invalid_string) ++ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string); ++ else ++ snprintf(tmp, sizeof(tmp), str_frmt->string, ++ str_frmt->params[0], ++ str_frmt->params[1], ++ str_frmt->params[2], ++ str_frmt->params[3], ++ str_frmt->params[4], ++ str_frmt->params[5], ++ str_frmt->params[6]); + + trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, + str_frmt->event_id, tmp); +@@ -609,6 +654,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, + return 0; + } + ++static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_string_format *cur_string) ++{ ++ cur_string->invalid_string = true; ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -619,12 +671,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + +- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); +- cur_string->last_param_num = 0; + cur_string->event_id = tracer_event->event_id; + cur_string->tmsn = tracer_event->string_event.tmsn; + cur_string->timestamp = tracer_event->string_event.timestamp; + cur_string->lost = tracer_event->lost_event; ++ cur_string->last_param_num = 0; ++ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s Invalid format string parameters\n", ++ __func__); ++ mlx5_tracer_handle_bad_format_string(tracer, cur_string); ++ return 0; ++ } + if (cur_string->num_of_params == 0) /* trace with no params */ + list_add_tail(&cur_string->list, &tracer->ready_strings_list); + } else { +@@ -634,6 +692,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + __func__, tracer_event->string_event.tmsn); + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s string parameter of invalid string, dumping\n", ++ __func__); ++ return 0; ++ } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { + pr_debug("%s Number of params exceeds the max (%d)\n", +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 5c548bb74f07b..30d0bcba88479 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -125,6 +125,7 @@ struct tracer_string_format { + struct list_head list; + u32 timestamp; + bool lost; ++ bool invalid_string; + }; + + enum mlx5_fw_tracer_ownership_state { +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-make-enable_mpesw-idempotent.patch b/queue-6.18/net-mlx5-make-enable_mpesw-idempotent.patch new file mode 100644 index 0000000000..e9bf2c0a56 --- /dev/null +++ b/queue-6.18/net-mlx5-make-enable_mpesw-idempotent.patch @@ -0,0 +1,58 @@ +From 3e334e7c3cf3ee987e72cc2b30df6397714d5888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Dec 2025 17:13:27 +0200 +Subject: net/mlx5: make enable_mpesw idempotent + +From: Moshe Shemesh + +[ Upstream commit cd7671ef4cf2edf73cd2a3dca3a2f522a4525bf5 ] + +The enable_mpesw() function returns -EINVAL if ldev->mode is not +MLX5_LAG_MODE_NONE. This means attempting to enable MPESW mode when it's +already enabled will fail. In contrast, disable_mpesw() properly checks +if the mode is MLX5_LAG_MODE_MPESW before proceeding, making it +naturally idempotent and safe to call multiple times. + +Fix enable_mpesw() to return success if mpesw is already enabled. + +Fixes: a32327a3a02c ("net/mlx5: Lag, Control MultiPort E-Switch single FDB mode") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/1764602008-1334866-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +index aad52d3a90e68..2d86af8f0d9b8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +@@ -67,12 +67,19 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev) + + static int enable_mpesw(struct mlx5_lag *ldev) + { +- int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); + struct mlx5_core_dev *dev0; + int err; ++ int idx; + int i; + +- if (idx < 0 || ldev->mode != MLX5_LAG_MODE_NONE) ++ if (ldev->mode == MLX5_LAG_MODE_MPESW) ++ return 0; ++ ++ if (ldev->mode != MLX5_LAG_MODE_NONE) ++ return -EINVAL; ++ ++ idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); ++ if (idx < 0) + return -EINVAL; + + dev0 = ldev->pf[idx].dev; +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5-serialize-firmware-reset-with-devlink.patch b/queue-6.18/net-mlx5-serialize-firmware-reset-with-devlink.patch new file mode 100644 index 0000000000..cc7f170eb6 --- /dev/null +++ b/queue-6.18/net-mlx5-serialize-firmware-reset-with-devlink.patch @@ -0,0 +1,209 @@ +From 6150f84808fd7854d1679bbc6302a816b575502b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:13 +0200 +Subject: net/mlx5: Serialize firmware reset with devlink + +From: Shay Drory + +[ Upstream commit 367e501f8b095eca08d2eb0ba4ccea5b5e82c169 ] + +The firmware reset mechanism can be triggered by asynchronous events, +which may race with other devlink operations like devlink reload or +devlink dev eswitch set, potentially leading to inconsistent states. + +This patch addresses the race by using the devl_lock to serialize the +firmware reset against other devlink operations. When a reset is +requested, the driver attempts to acquire the lock. If successful, it +sets a flag to block devlink reload or eswitch changes, ACKs the reset +to firmware and then releases the lock. If the lock is already held by +another operation, the driver NACKs the firmware reset request, +indicating that the reset cannot proceed. + +Firmware reset does not keep the devl_lock and instead uses an internal +firmware reset bit. This is because firmware resets can be triggered by +asynchronous events, and processed in different threads. It is illegal +and unsafe to acquire a lock in one thread and attempt to release it in +another, as lock ownership is intrinsically thread-specific. + +This change ensures that firmware resets and other devlink operations +are mutually exclusive during the critical reset request phase, +preventing race conditions. + +Fixes: 38b9f903f22b ("net/mlx5: Handle sync reset request event") +Signed-off-by: Shay Drory +Reviewed-by: Mateusz Berezecki +Reviewed-by: Moshe Shemesh +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/devlink.c | 5 +++ + .../mellanox/mlx5/core/eswitch_offloads.c | 6 +++ + .../ethernet/mellanox/mlx5/core/fw_reset.c | 45 +++++++++++++++++-- + .../ethernet/mellanox/mlx5/core/fw_reset.h | 1 + + 4 files changed, 53 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 887adf4807d16..ea77fbd98396a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -197,6 +197,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, + struct pci_dev *pdev = dev->pdev; + int ret = 0; + ++ if (mlx5_fw_reset_in_progress(dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Can't reload during firmware reset"); ++ return -EBUSY; ++ } ++ + if (mlx5_dev_is_lightweight(dev)) { + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 44a142a041b2f..784130cdf6c07 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -52,6 +52,7 @@ + #include "devlink.h" + #include "lag/lag.h" + #include "en/tc/post_meter.h" ++#include "fw_reset.h" + + /* There are two match-all miss flows, one for unicast dst mac and + * one for multicast. +@@ -3807,6 +3808,11 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, + if (IS_ERR(esw)) + return PTR_ERR(esw); + ++ if (mlx5_fw_reset_in_progress(esw->dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Can't change eswitch mode during firmware reset"); ++ return -EBUSY; ++ } ++ + if (esw_mode_from_devlink(mode, &mlx5_mode)) + return -EINVAL; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 33df0418e5754..4544f1968f73f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -15,6 +15,7 @@ enum { + MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, + MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, + MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, ++ MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, + }; + + struct mlx5_fw_reset { +@@ -127,6 +128,16 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty + return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL); + } + ++bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev) ++{ ++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ ++ if (!fw_reset) ++ return false; ++ ++ return test_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); ++} ++ + static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev, + u8 *reset_method) + { +@@ -242,6 +253,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); + devl_unlock(devlink); + } ++ ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + } + + static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) +@@ -461,27 +474,48 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, + reset_request_work); + struct mlx5_core_dev *dev = fw_reset->dev; ++ bool nack_request = false; ++ struct devlink *devlink; + int err; + + err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method); +- if (err) ++ if (err) { ++ nack_request = true; + mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err); ++ } else if (!mlx5_is_reset_now_capable(dev, fw_reset->reset_method) || ++ test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, ++ &fw_reset->reset_flags)) { ++ nack_request = true; ++ } + +- if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || +- !mlx5_is_reset_now_capable(dev, fw_reset->reset_method)) { ++ devlink = priv_to_devlink(dev); ++ /* For external resets, try to acquire devl_lock. Skip if devlink reset is ++ * pending (lock already held) ++ */ ++ if (nack_request || ++ (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, ++ &fw_reset->reset_flags) && ++ !devl_trylock(devlink))) { + err = mlx5_fw_reset_set_reset_sync_nack(dev); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", + err ? "Failed" : "Sent"); + return; + } ++ + if (mlx5_sync_reset_set_reset_requested(dev)) +- return; ++ goto unlock; ++ ++ set_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + + err = mlx5_fw_reset_set_reset_sync_ack(dev); + if (err) + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err); + else + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n"); ++ ++unlock: ++ if (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) ++ devl_unlock(devlink); + } + + static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id) +@@ -721,6 +755,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work) + + if (mlx5_sync_reset_clear_reset_requested(dev, true)) + return; ++ ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); + } + +@@ -757,6 +793,7 @@ static void mlx5_sync_reset_timeout_work(struct work_struct *work) + + if (mlx5_sync_reset_clear_reset_requested(dev, true)) + return; ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Timeout.\n"); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +index d5b28525c960d..2d96b2adc1cdf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +@@ -10,6 +10,7 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty + int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, + struct netlink_ext_ack *extack); + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); ++bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev); + + int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); + void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5e-avoid-unregistering-psp-twice.patch b/queue-6.18/net-mlx5e-avoid-unregistering-psp-twice.patch new file mode 100644 index 0000000000..f4f66d592d --- /dev/null +++ b/queue-6.18/net-mlx5e-avoid-unregistering-psp-twice.patch @@ -0,0 +1,58 @@ +From 6bae7d8d5096cd5c385bd6f33c25463a149c51a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Dec 2025 17:13:28 +0200 +Subject: net/mlx5e: Avoid unregistering PSP twice + +From: Cosmin Ratiu + +[ Upstream commit 35e93736f69963337912594eb3951ab320b77521 ] + +PSP is unregistered twice in: +_mlx5e_remove -> mlx5e_psp_unregister +mlx5e_nic_cleanup -> mlx5e_psp_unregister + +This leads to a refcount underflow in some conditions: +------------[ cut here ]------------ +refcount_t: underflow; use-after-free. +WARNING: CPU: 2 PID: 1694 at lib/refcount.c:28 refcount_warn_saturate+0xd8/0xe0 +[...] + mlx5e_psp_unregister+0x26/0x50 [mlx5_core] + mlx5e_nic_cleanup+0x26/0x90 [mlx5_core] + mlx5e_remove+0xe6/0x1f0 [mlx5_core] + auxiliary_bus_remove+0x18/0x30 + device_release_driver_internal+0x194/0x1f0 + bus_remove_device+0xc6/0x130 + device_del+0x159/0x3c0 + mlx5_rescan_drivers_locked+0xbc/0x2a0 [mlx5_core] +[...] + +Do not directly remove psp from the _mlx5e_remove path, the PSP cleanup +happens as part of profile cleanup. + +Fixes: 89ee2d92f66c ("net/mlx5e: Support PSP offload functionality") +Signed-off-by: Cosmin Ratiu +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/1764602008-1334866-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 5e17eae81f4b3..1545f9c008f49 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -6805,7 +6805,6 @@ static void _mlx5e_remove(struct auxiliary_device *adev) + * is already unregistered before changing to NIC profile. + */ + if (priv->netdev->reg_state == NETREG_REGISTERED) { +- mlx5e_psp_unregister(priv); + unregister_netdev(priv->netdev); + _mlx5e_suspend(adev, false); + } else { +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5e-don-t-include-psp-in-the-hard-mtu-calculat.patch b/queue-6.18/net-mlx5e-don-t-include-psp-in-the-hard-mtu-calculat.patch new file mode 100644 index 0000000000..5f2565ae87 --- /dev/null +++ b/queue-6.18/net-mlx5e-don-t-include-psp-in-the-hard-mtu-calculat.patch @@ -0,0 +1,53 @@ +From e2c475063147bd5dd3e74cd143fb7d55717c9c32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:17 +0200 +Subject: net/mlx5e: Don't include PSP in the hard MTU calculations + +From: Cosmin Ratiu + +[ Upstream commit 4198a14c8c6252fd1191afaa742dd515dcaf3487 ] + +Commit [1] added the 40 bytes required by the PSP header+trailer and the +UDP header to MLX5E_ETH_HARD_MTU, which limits the device-wide max +software MTU that could be set. This is not okay, because most packets +are not PSP packets and it doesn't make sense to always reserve space +for headers which won't get added in most cases. + +As it turns out, for TCP connections, PSP overhead is already taken into +account in the TCP MSS calculations via inet_csk(sk)->icsk_ext_hdr_len. +This was added in commit [2]. This means that the extra space reserved +in the hard MTU for mlx5 ends up unused and wasted. + +Remove the unnecessary 40 byte reservation from hard MTU. + +[1] commit e5a1861a298e ("net/mlx5e: Implement PSP Tx data path") +[2] commit e97269257fe4 ("net: psp: update the TCP MSS to reflect PSP +packet overhead") + +Fixes: e5a1861a298e ("net/mlx5e: Implement PSP Tx data path") +Signed-off-by: Cosmin Ratiu +Reviewed-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-10-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index a163f81f07c13..a6479e4d8d8c6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -69,7 +69,7 @@ struct page_pool; + #define MLX5E_METADATA_ETHER_TYPE (0x8CE4) + #define MLX5E_METADATA_ETHER_LEN 8 + +-#define MLX5E_ETH_HARD_MTU (ETH_HLEN + PSP_ENCAP_HLEN + PSP_TRL_SIZE + VLAN_HLEN + ETH_FCS_LEN) ++#define MLX5E_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) + + #define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu)) + #define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu)) +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5e-trigger-neighbor-resolution-for-unresolved.patch b/queue-6.18/net-mlx5e-trigger-neighbor-resolution-for-unresolved.patch new file mode 100644 index 0000000000..daef2b2c84 --- /dev/null +++ b/queue-6.18/net-mlx5e-trigger-neighbor-resolution-for-unresolved.patch @@ -0,0 +1,60 @@ +From a6a9c9885bf0de63ec9d74b3d44e5e5290e8ee03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:15 +0200 +Subject: net/mlx5e: Trigger neighbor resolution for unresolved destinations + +From: Jianbo Liu + +[ Upstream commit 9ab89bde13e5251e1d0507e1cc426edcdfe19142 ] + +When initializing the MAC addresses for an outbound IPsec packet offload +rule in mlx5e_ipsec_init_macs, the call to dst_neigh_lookup is used to +find the next-hop neighbor (typically the gateway in tunnel mode). +This call might create a new neighbor entry if one doesn't already +exist. This newly created entry starts in the INCOMPLETE state, as the +kernel hasn't yet sent an ARP or NDISC probe to resolve the MAC +address. In this case, neigh_ha_snapshot will correctly return an +all-zero MAC address. + +IPsec packet offload requires the actual next-hop MAC address to +program the rule correctly. If the neighbor state is INCOMPLETE when +the rule is created, the hardware rule is programmed with an all-zero +destination MAC address. Packets sent using this rule will be +subsequently dropped by the receiving network infrastructure or host. + +This patch adds a check specifically for the outbound offload path. If +neigh_ha_snapshot returns an all-zero MAC address, it proactively +calls neigh_event_send(n, NULL). This ensures the kernel immediately +sends the initial ARP or NDISC probe if one isn't already pending, +accelerating the resolution process. This helps prevent the hardware +rule from being programmed with an invalid MAC address and avoids +packet drops due to unresolved neighbors. + +Fixes: 71670f766b8f ("net/mlx5e: Support routed networks during IPsec MACs initialization") +Signed-off-by: Jianbo Liu +Reviewed-by: Leon Romanovsky +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-8-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +index 6c79b9cea2efb..a8fb4bec369cf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +@@ -358,6 +358,9 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry, + + neigh_ha_snapshot(addr, n, netdev); + ether_addr_copy(dst, addr); ++ if (attrs->dir == XFRM_DEV_OFFLOAD_OUT && ++ is_zero_ether_addr(addr)) ++ neigh_event_send(n, NULL); + dst_release(rt_dst_entry); + neigh_release(n); + return; +-- +2.51.0 + diff --git a/queue-6.18/net-mlx5e-use-ip6_dst_lookup-instead-of-ipv6_dst_loo.patch b/queue-6.18/net-mlx5e-use-ip6_dst_lookup-instead-of-ipv6_dst_loo.patch new file mode 100644 index 0000000000..e4a887ab71 --- /dev/null +++ b/queue-6.18/net-mlx5e-use-ip6_dst_lookup-instead-of-ipv6_dst_loo.patch @@ -0,0 +1,50 @@ +From 9d1d1f419b2c51ec92b664ab944e07034baf7156 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:14 +0200 +Subject: net/mlx5e: Use ip6_dst_lookup instead of ipv6_dst_lookup_flow for MAC + init + +From: Jianbo Liu + +[ Upstream commit e35d7da8dd9e55b37c3e8ab548f6793af0c2ab49 ] + +Replace ipv6_stub->ipv6_dst_lookup_flow() with ip6_dst_lookup() in +mlx5e_ipsec_init_macs() since IPsec transformations are not needed +during Security Association setup - only basic routing information is +required for nexthop MAC address resolution. + +This resolves an issue where XfrmOutNoStates error counter would be +incremented when xfrm policy is configured before xfrm state, as the +IPsec-aware routing function would attempt policy checks during SA +initialization. + +Fixes: 71670f766b8f ("net/mlx5e: Support routed networks during IPsec MACs initialization") +Signed-off-by: Jianbo Liu +Reviewed-by: Leon Romanovsky +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-7-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +index 35d9530037a65..6c79b9cea2efb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +@@ -342,9 +342,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry, + rt_dst_entry = &rt->dst; + break; + case AF_INET6: +- rt_dst_entry = ipv6_stub->ipv6_dst_lookup_flow( +- dev_net(netdev), NULL, &fl6, NULL); +- if (IS_ERR(rt_dst_entry)) ++ if (!IS_ENABLED(CONFIG_IPV6) || ++ ip6_dst_lookup(dev_net(netdev), NULL, &rt_dst_entry, &fl6)) + goto neigh; + break; + default: +-- +2.51.0 + diff --git a/queue-6.18/net-openvswitch-fix-middle-attribute-validation-in-p.patch b/queue-6.18/net-openvswitch-fix-middle-attribute-validation-in-p.patch new file mode 100644 index 0000000000..ccde01db3a --- /dev/null +++ b/queue-6.18/net-openvswitch-fix-middle-attribute-validation-in-p.patch @@ -0,0 +1,112 @@ +From d7e5658bcb2f8f2e330ae57a372239d56ad6254a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:53:32 +0100 +Subject: net: openvswitch: fix middle attribute validation in push_nsh() + action + +From: Ilya Maximets + +[ Upstream commit 5ace7ef87f059d68b5f50837ef3e8a1a4870c36e ] + +The push_nsh() action structure looks like this: + + OVS_ACTION_ATTR_PUSH_NSH(OVS_KEY_ATTR_NSH(OVS_NSH_KEY_ATTR_BASE,...)) + +The outermost OVS_ACTION_ATTR_PUSH_NSH attribute is OK'ed by the +nla_for_each_nested() inside __ovs_nla_copy_actions(). The innermost +OVS_NSH_KEY_ATTR_BASE/MD1/MD2 are OK'ed by the nla_for_each_nested() +inside nsh_key_put_from_nlattr(). But nothing checks if the attribute +in the middle is OK. We don't even check that this attribute is the +OVS_KEY_ATTR_NSH. We just do a double unwrap with a pair of nla_data() +calls - first time directly while calling validate_push_nsh() and the +second time as part of the nla_for_each_nested() macro, which isn't +safe, potentially causing invalid memory access if the size of this +attribute is incorrect. The failure may not be noticed during +validation due to larger netlink buffer, but cause trouble later during +action execution where the buffer is allocated exactly to the size: + + BUG: KASAN: slab-out-of-bounds in nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + Read of size 184 at addr ffff88816459a634 by task a.out/22624 + + CPU: 8 UID: 0 PID: 22624 6.18.0-rc7+ #115 PREEMPT(voluntary) + Call Trace: + + dump_stack_lvl+0x51/0x70 + print_address_description.constprop.0+0x2c/0x390 + kasan_report+0xdd/0x110 + kasan_check_range+0x35/0x1b0 + __asan_memcpy+0x20/0x60 + nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + push_nsh+0x82/0x120 [openvswitch] + do_execute_actions+0x1405/0x2840 [openvswitch] + ovs_execute_actions+0xd5/0x3b0 [openvswitch] + ovs_packet_cmd_execute+0x949/0xdb0 [openvswitch] + genl_family_rcv_msg_doit+0x1d6/0x2b0 + genl_family_rcv_msg+0x336/0x580 + genl_rcv_msg+0x9f/0x130 + netlink_rcv_skb+0x11f/0x370 + genl_rcv+0x24/0x40 + netlink_unicast+0x73e/0xaa0 + netlink_sendmsg+0x744/0xbf0 + __sys_sendto+0x3d6/0x450 + do_syscall_64+0x79/0x2c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + +Let's add some checks that the attribute is properly sized and it's +the only one attribute inside the action. Technically, there is no +real reason for OVS_KEY_ATTR_NSH to be there, as we know that we're +pushing an NSH header already, it just creates extra nesting, but +that's how uAPI works today. So, keeping as it is. + +Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") +Reported-by: Junvy Yang +Signed-off-by: Ilya Maximets +Acked-by: Eelco Chaudron echaudro@redhat.com +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20251204105334.900379-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 1cb4f97335d87..2d536901309ea 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2802,13 +2802,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, + return err; + } + +-static bool validate_push_nsh(const struct nlattr *attr, bool log) ++static bool validate_push_nsh(const struct nlattr *a, bool log) + { ++ struct nlattr *nsh_key = nla_data(a); + struct sw_flow_match match; + struct sw_flow_key key; + ++ /* There must be one and only one NSH header. */ ++ if (!nla_ok(nsh_key, nla_len(a)) || ++ nla_total_size(nla_len(nsh_key)) != nla_len(a) || ++ nla_type(nsh_key) != OVS_KEY_ATTR_NSH) ++ return false; ++ + ovs_match_init(&match, &key, true, NULL); +- return !nsh_key_put_from_nlattr(attr, &match, false, true, log); ++ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log); + } + + /* Return false if there are any non-masked bits set. +@@ -3389,7 +3396,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, + return -EINVAL; + } + mac_proto = MAC_PROTO_NONE; +- if (!validate_push_nsh(nla_data(a), log)) ++ if (!validate_push_nsh(a, log)) + return -EINVAL; + break; + +-- +2.51.0 + diff --git a/queue-6.18/net-phy-realtek-allow-clkout-to-be-disabled-on-rtl82.patch b/queue-6.18/net-phy-realtek-allow-clkout-to-be-disabled-on-rtl82.patch new file mode 100644 index 0000000000..174211ce45 --- /dev/null +++ b/queue-6.18/net-phy-realtek-allow-clkout-to-be-disabled-on-rtl82.patch @@ -0,0 +1,112 @@ +From b08ce64531ce5951280e7d19860265796e7ba077 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 01:40:31 +0200 +Subject: net: phy: realtek: allow CLKOUT to be disabled on + RTL8211F(D)(I)-VD-CG + +From: Vladimir Oltean + +[ Upstream commit e1a31c41bef678afe0d99b7f0dc3711a80c68447 ] + +Add CLKOUT disable support for RTL8211F(D)(I)-VD-CG. Like with other PHY +variants, this feature might be requested by customers when the clock +output is not used, in order to reduce electromagnetic interference (EMI). + +In the common driver, the CLKOUT configuration is done through PHYCR2. +The RTL_8211FVD_PHYID is singled out as not having that register, and +execution in rtl8211f_config_init() returns early after commit +2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not +present"). + +But actually CLKOUT is configured through a different register for this +PHY. Instead of pretending this is PHYCR2 (which it is not), just add +some code for modifying this register inside the rtl8211f_disable_clk_out() +function, and move that outside the code portion that runs only if +PHYCR2 exists. + +In practice this reorders the PHYCR2 writes to disable PHY-mode EEE and +to disable the CLKOUT for the normal RTL8211F variants, but this should +be perfectly fine. + +It was not noted that RTL8211F(D)(I)-VD-CG would need a genphy_soft_reset() +call after disabling the CLKOUT. Despite that, we do it out of caution +and for symmetry with the other RTL8211F models. + +Co-developed-by: Clark Wang +Signed-off-by: Clark Wang +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-5-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4f0638b12451 ("net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/realtek/realtek_main.c | 31 ++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c +index daf2457b378bf..f0348b92beec3 100644 +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -89,6 +89,14 @@ + #define RTL8211F_LEDCR_MASK GENMASK(4, 0) + #define RTL8211F_LEDCR_SHIFT 5 + ++/* RTL8211F(D)(I)-VD-CG CLKOUT configuration is specified via magic values ++ * to undocumented register pages. The names here do not reflect the datasheet. ++ * Unlike other PHY models, CLKOUT configuration does not go through PHYCR2. ++ */ ++#define RTL8211FVD_CLKOUT_PAGE 0xd05 ++#define RTL8211FVD_CLKOUT_REG 0x11 ++#define RTL8211FVD_CLKOUT_EN BIT(8) ++ + /* RTL8211F RGMII configuration */ + #define RTL8211F_RGMII_PAGE 0xd08 + +@@ -626,8 +634,13 @@ static int rtl8211f_config_clk_out(struct phy_device *phydev) + if (!priv->disable_clk_out) + return 0; + +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, +- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); ++ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) ++ ret = phy_modify_paged(phydev, RTL8211FVD_CLKOUT_PAGE, ++ RTL8211FVD_CLKOUT_REG, ++ RTL8211FVD_CLKOUT_EN, 0); ++ else ++ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, ++ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); + if (ret) + return ret; + +@@ -653,6 +666,13 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret) + return ret; + ++ ret = rtl8211f_config_clk_out(phydev); ++ if (ret) { ++ dev_err(dev, "clkout configuration failed: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ + /* RTL8211FVD has no PHYCR2 register */ + if (phydev->drv->phy_id == RTL_8211FVD_PHYID) + return 0; +@@ -663,13 +683,6 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret) + return ret; + +- ret = rtl8211f_config_clk_out(phydev); +- if (ret) { +- dev_err(dev, "clkout configuration failed: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.18/net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch b/queue-6.18/net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch new file mode 100644 index 0000000000..cbbaa3add9 --- /dev/null +++ b/queue-6.18/net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch @@ -0,0 +1,69 @@ +From 3383ef741ca76eb06cff2d5db5b18b924c693100 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 01:40:33 +0200 +Subject: net: phy: realtek: create rtl8211f_config_phy_eee() helper + +From: Vladimir Oltean + +[ Upstream commit 4465ae435ddc0162d5033a543658449d53d46d08 ] + +To simplify the rtl8211f_config_init() control flow and get rid of +"early" returns for PHYs where the PHYCR2 register is absent, move the +entire logic sub-block that deals with disabling PHY-mode EEE to a +separate function. There, it is much more obvious what the early +"return 0" skips, and it becomes more difficult to accidentally skip +unintended stuff. + +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251117234033.345679-7-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4f0638b12451 ("net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/realtek/realtek_main.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c +index 35f40bfdaf113..2c661346050f1 100644 +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -662,6 +662,17 @@ static int rtl8211f_config_aldps(struct phy_device *phydev) + mask, mask); + } + ++static int rtl8211f_config_phy_eee(struct phy_device *phydev) ++{ ++ /* RTL8211FVD has no PHYCR2 register */ ++ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) ++ return 0; ++ ++ /* Disable PHY-mode EEE so LPI is passed to the MAC */ ++ return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, ++ RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); ++} ++ + static int rtl8211f_config_init(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -685,17 +696,7 @@ static int rtl8211f_config_init(struct phy_device *phydev) + return ret; + } + +- /* RTL8211FVD has no PHYCR2 register */ +- if (phydev->drv->phy_id == RTL_8211FVD_PHYID) +- return 0; +- +- /* Disable PHY-mode EEE so LPI is passed to the MAC */ +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, +- RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); +- if (ret) +- return ret; +- +- return 0; ++ return rtl8211f_config_phy_eee(phydev); + } + + static int rtl821x_suspend(struct phy_device *phydev) +-- +2.51.0 + diff --git a/queue-6.18/net-phy-realtek-eliminate-has_phycr2-variable.patch b/queue-6.18/net-phy-realtek-eliminate-has_phycr2-variable.patch new file mode 100644 index 0000000000..b17bc94c06 --- /dev/null +++ b/queue-6.18/net-phy-realtek-eliminate-has_phycr2-variable.patch @@ -0,0 +1,66 @@ +From 3f9f0ea232dec6ab6bdbfe91ce8e93841f5c703a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 01:40:30 +0200 +Subject: net: phy: realtek: eliminate has_phycr2 variable + +From: Vladimir Oltean + +[ Upstream commit 910ac7bfb1af1ae4cd141ef80e03a6729213c189 ] + +This variable is assigned in rtl821x_probe() and used in +rtl8211f_config_init(), which is more complex than it needs to be. +Simply testing the same condition from rtl821x_probe() in +rtl8211f_config_init() yields the same result (the PHY driver ID is a +runtime invariant), but with one temporary variable less. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-4-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4f0638b12451 ("net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/realtek/realtek_main.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c +index 1625919a47be8..daf2457b378bf 100644 +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -167,7 +167,6 @@ MODULE_LICENSE("GPL"); + + struct rtl821x_priv { + u16 phycr1; +- bool has_phycr2; + bool disable_clk_out; + struct clk *clk; + /* rtl8211f */ +@@ -218,7 +217,6 @@ static int rtl821x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; + struct rtl821x_priv *priv; +- u32 phy_id = phydev->drv->phy_id; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +@@ -238,7 +236,6 @@ static int rtl821x_probe(struct phy_device *phydev) + if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) + priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; + +- priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); + priv->disable_clk_out = of_property_read_bool(dev->of_node, + "realtek,clkout-disable"); + +@@ -656,7 +653,8 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret) + return ret; + +- if (!priv->has_phycr2) ++ /* RTL8211FVD has no PHYCR2 register */ ++ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) + return 0; + + /* Disable PHY-mode EEE so LPI is passed to the MAC */ +-- +2.51.0 + diff --git a/queue-6.18/net-phy-realtek-eliminate-priv-phycr1-variable.patch b/queue-6.18/net-phy-realtek-eliminate-priv-phycr1-variable.patch new file mode 100644 index 0000000000..1c1ce0d26a --- /dev/null +++ b/queue-6.18/net-phy-realtek-eliminate-priv-phycr1-variable.patch @@ -0,0 +1,118 @@ +From 7a1f905e22d2ce2c2dc90683dbde628093649d23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 01:40:32 +0200 +Subject: net: phy: realtek: eliminate priv->phycr1 variable + +From: Vladimir Oltean + +[ Upstream commit bb78b71faf60d11a15f07e3390fcfd31e5e523bb ] + +Previous changes have replaced the machine-level priv->phycr2 with a +high-level priv->disable_clk_out. This created a discrepancy with +priv->phycr1 which is resolved here, for uniformity. + +One advantage of this new implementation is that we don't read +priv->phycr1 in rtl821x_probe() if we're never going to modify it. + +We never test the positive return code from phy_modify_mmd_changed(), so +we could just as well use phy_modify_mmd(). + +I took the ALDPS feature description from commit d90db36a9e74 ("net: +phy: realtek: add dt property to enable ALDPS mode") and transformed it +into a function comment - the feature is sufficiently non-obvious to +deserve that. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-6-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4f0638b12451 ("net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/realtek/realtek_main.c | 44 ++++++++++++++++---------- + 1 file changed, 28 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c +index f0348b92beec3..35f40bfdaf113 100644 +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -174,7 +174,7 @@ MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); + + struct rtl821x_priv { +- u16 phycr1; ++ bool enable_aldps; + bool disable_clk_out; + struct clk *clk; + /* rtl8211f */ +@@ -225,7 +225,6 @@ static int rtl821x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; + struct rtl821x_priv *priv; +- int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -236,14 +235,8 @@ static int rtl821x_probe(struct phy_device *phydev) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to get phy clock\n"); + +- ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1); +- if (ret < 0) +- return ret; +- +- priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); +- if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) +- priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; +- ++ priv->enable_aldps = of_property_read_bool(dev->of_node, ++ "realtek,aldps-enable"); + priv->disable_clk_out = of_property_read_bool(dev->of_node, + "realtek,clkout-disable"); + +@@ -647,17 +640,36 @@ static int rtl8211f_config_clk_out(struct phy_device *phydev) + return genphy_soft_reset(phydev); + } + +-static int rtl8211f_config_init(struct phy_device *phydev) ++/* Advance Link Down Power Saving (ALDPS) mode changes crystal/clock behaviour, ++ * which causes the RXC clock signal to stop for tens to hundreds of ++ * milliseconds. ++ * ++ * Some MACs need the RXC clock to support their internal RX logic, so ALDPS is ++ * only enabled based on an opt-in device tree property. ++ */ ++static int rtl8211f_config_aldps(struct phy_device *phydev) + { + struct rtl821x_priv *priv = phydev->priv; ++ u16 mask = RTL8211F_ALDPS_PLL_OFF | ++ RTL8211F_ALDPS_ENABLE | ++ RTL8211F_ALDPS_XTAL_OFF; ++ ++ /* The value is preserved if the device tree property is absent */ ++ if (!priv->enable_aldps) ++ return 0; ++ ++ return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, ++ mask, mask); ++} ++ ++static int rtl8211f_config_init(struct phy_device *phydev) ++{ + struct device *dev = &phydev->mdio.dev; + int ret; + +- ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, +- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, +- priv->phycr1); +- if (ret < 0) { +- dev_err(dev, "aldps mode configuration failed: %pe\n", ++ ret = rtl8211f_config_aldps(phydev); ++ if (ret) { ++ dev_err(dev, "aldps mode configuration failed: %pe\n", + ERR_PTR(ret)); + return ret; + } +-- +2.51.0 + diff --git a/queue-6.18/net-phy-realtek-eliminate-priv-phycr2-variable.patch b/queue-6.18/net-phy-realtek-eliminate-priv-phycr2-variable.patch new file mode 100644 index 0000000000..30b47a5887 --- /dev/null +++ b/queue-6.18/net-phy-realtek-eliminate-priv-phycr2-variable.patch @@ -0,0 +1,112 @@ +From 8a85881e510d36d36c9d21a23f11ba6950918ba1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 01:40:29 +0200 +Subject: net: phy: realtek: eliminate priv->phycr2 variable + +From: Vladimir Oltean + +[ Upstream commit 27033d06917758d47162581da7e9de8004049dee ] + +The RTL8211F(D)(I)-VD-CG PHY also has support for disabling the CLKOUT, +and we'd like to introduce the "realtek,clkout-disable" property for +that. + +But it isn't done through the PHYCR2 register, and it becomes awkward to +have the driver pretend that it is. So just replace the machine-level +"u16 phycr2" variable with a logical "bool disable_clk_out", which +scales better to the other PHY as well. + +The change is a complete functional equivalent. Before, if the device +tree property was absent, priv->phycr2 would contain the RTL8211F_CLKOUT_EN +bit as read from hardware. Now, we don't save priv->phycr2, but we just +don't call phy_modify_paged() on it. Also, we can simply call +phy_modify_paged() with the "set" argument to 0. + +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251117234033.345679-3-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4f0638b12451 ("net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/realtek/realtek_main.c | 38 ++++++++++++++++---------- + 1 file changed, 23 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c +index b26f4d1c6bbfa..1625919a47be8 100644 +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -167,8 +167,8 @@ MODULE_LICENSE("GPL"); + + struct rtl821x_priv { + u16 phycr1; +- u16 phycr2; + bool has_phycr2; ++ bool disable_clk_out; + struct clk *clk; + /* rtl8211f */ + u16 iner; +@@ -239,15 +239,8 @@ static int rtl821x_probe(struct phy_device *phydev) + priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; + + priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); +- if (priv->has_phycr2) { +- ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2); +- if (ret < 0) +- return ret; +- +- priv->phycr2 = ret & RTL8211F_CLKOUT_EN; +- if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) +- priv->phycr2 &= ~RTL8211F_CLKOUT_EN; +- } ++ priv->disable_clk_out = of_property_read_bool(dev->of_node, ++ "realtek,clkout-disable"); + + phydev->priv = priv; + +@@ -627,6 +620,23 @@ static int rtl8211f_config_rgmii_delay(struct phy_device *phydev) + return 0; + } + ++static int rtl8211f_config_clk_out(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* The value is preserved if the device tree property is absent */ ++ if (!priv->disable_clk_out) ++ return 0; ++ ++ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, ++ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); ++ if (ret) ++ return ret; ++ ++ return genphy_soft_reset(phydev); ++} ++ + static int rtl8211f_config_init(struct phy_device *phydev) + { + struct rtl821x_priv *priv = phydev->priv; +@@ -655,16 +665,14 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret) + return ret; + +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, +- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, +- priv->phycr2); +- if (ret < 0) { ++ ret = rtl8211f_config_clk_out(phydev); ++ if (ret) { + dev_err(dev, "clkout configuration failed: %pe\n", + ERR_PTR(ret)); + return ret; + } + +- return genphy_soft_reset(phydev); ++ return 0; + } + + static int rtl821x_suspend(struct phy_device *phydev) +-- +2.51.0 + diff --git a/queue-6.18/net-phy-rtl8211fvd-restore-disabling-of-phy-mode-eee.patch b/queue-6.18/net-phy-rtl8211fvd-restore-disabling-of-phy-mode-eee.patch new file mode 100644 index 0000000000..4b4f906318 --- /dev/null +++ b/queue-6.18/net-phy-rtl8211fvd-restore-disabling-of-phy-mode-eee.patch @@ -0,0 +1,71 @@ +From f5fe162183ed67188148861c3f1b31494e5d9520 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 10:07:42 +0100 +Subject: net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE + +From: Ivan Galkin + +[ Upstream commit 4f0638b12451112de4138689fa679315c8d388dc ] + +When support for RTL8211F(D)(I)-VD-CG was introduced in commit +bb726b753f75 ("net: phy: realtek: add support for RTL8211F(D)(I)-VD-CG") +the implementation assumed that this PHY model doesn't have the +control register PHYCR2 (Page 0xa43 Address 0x19). This +assumption was based on the differences in CLKOUT configurations +between RTL8211FVD and the remaining RTL8211F PHYs. In the latter +commit 2c67301584f2 +("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present") +this assumption was expanded to the PHY-mode EEE. + +I performed tests on RTL8211FI-VD-CG and confirmed that disabling +PHY-mode EEE works correctly and is uniform with other PHYs +supported by the driver. To validate the correctness, +I contacted Realtek support. Realtek confirmed that PHY-mode EEE on +RTL8211F(D)(I)-VD-CG is configured via Page 0xa43 Address 0x19 bit 5. + +Moreover, Realtek informed me that the most recent datasheet +for RTL8211F(D)(I)-VD-CG v1.1 is incomplete and the naming of +control registers is partly inconsistent. The errata I +received from Realtek corrects the naming as follows: + +| Register | Datasheet v1.1 | Errata | +|-------------------------|----------------|--------| +| Page 0xa44 Address 0x11 | PHYCR2 | PHYCR3 | +| Page 0xa43 Address 0x19 | N/A | PHYCR2 | + +This information confirms that the supposedly missing control register, +PHYCR2, exists in the RTL8211F(D)(I)-VD-CG under the same address and +the same name. It controls widely the same configs as other PHYs from +the RTL8211F series (e.g. PHY-mode EEE). Clock out configuration is an +exception. + +Given all this information, restore disabling of the PHY-mode EEE. + +Fixes: 2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present") +Signed-off-by: Ivan Galkin +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20251202-phy_eee-v1-1-fe0bf6ab3df0@axis.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/phy/realtek/realtek_main.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c +index 2c661346050f1..7c3d277efaf07 100644 +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -664,10 +664,6 @@ static int rtl8211f_config_aldps(struct phy_device *phydev) + + static int rtl8211f_config_phy_eee(struct phy_device *phydev) + { +- /* RTL8211FVD has no PHYCR2 register */ +- if (phydev->drv->phy_id == RTL_8211FVD_PHYID) +- return 0; +- + /* Disable PHY-mode EEE so LPI is passed to the MAC */ + return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, + RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); +-- +2.51.0 + diff --git a/queue-6.18/net-sched-ets-always-remove-class-from-active-list-b.patch b/queue-6.18/net-sched-ets-always-remove-class-from-active-list-b.patch new file mode 100644 index 0000000000..b66ac6dcb5 --- /dev/null +++ b/queue-6.18/net-sched-ets-always-remove-class-from-active-list-b.patch @@ -0,0 +1,232 @@ +From 79a8ef846bac934d8f609b925314bf6a15c0f166 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: net/sched: ets: Always remove class from active list before deleting + in ets_qdisc_change + +From: Jamal Hadi Salim + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 82635dd2cfa59..ae46643e596d3 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -652,7 +652,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.51.0 + diff --git a/queue-6.18/net-sched-ets-remove-drr-class-from-the-active-list-.patch b/queue-6.18/net-sched-ets-remove-drr-class-from-the-active-list-.patch new file mode 100644 index 0000000000..5a5e01f2bc --- /dev/null +++ b/queue-6.18/net-sched-ets-remove-drr-class-from-the-active-list-.patch @@ -0,0 +1,88 @@ +From bc0aea7ce3ca53393892c749d81fc995c26b753d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:01:24 -0300 +Subject: net/sched: ets: Remove drr class from the active list if it changes + to strict + +From: Victor Nogueira + +[ Upstream commit b1e125ae425aba9b45252e933ca8df52a843ec70 ] + +Whenever a user issues an ets qdisc change command, transforming a +drr class into a strict one, the ets code isn't checking whether that +class was in the active list and removing it. This means that, if a +user changes a strict class (which was in the active list) back to a drr +one, that class will be added twice to the active list [1]. + +Doing so with the following commands: + +tc qdisc add dev lo root handle 1: ets bands 2 strict 1 +tc qdisc add dev lo parent 1:2 handle 20: \ + tbf rate 8bit burst 100b latency 1s +tc filter add dev lo parent 1: basic classid 1:2 +ping -c1 -W0.01 -s 56 127.0.0.1 +tc qdisc change dev lo root handle 1: ets bands 2 strict 2 +tc qdisc change dev lo root handle 1: ets bands 2 strict 1 +ping -c1 -W0.01 -s 56 127.0.0.1 + +Will trigger the following splat with list debug turned on: + +[ 59.279014][ T365] ------------[ cut here ]------------ +[ 59.279452][ T365] list_add double add: new=ffff88801d60e350, prev=ffff88801d60e350, next=ffff88801d60e2c0. +[ 59.280153][ T365] WARNING: CPU: 3 PID: 365 at lib/list_debug.c:35 __list_add_valid_or_report+0x17f/0x220 +[ 59.280860][ T365] Modules linked in: +[ 59.281165][ T365] CPU: 3 UID: 0 PID: 365 Comm: tc Not tainted 6.18.0-rc7-00105-g7e9f13163c13-dirty #239 PREEMPT(voluntary) +[ 59.281977][ T365] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 59.282391][ T365] RIP: 0010:__list_add_valid_or_report+0x17f/0x220 +[ 59.282842][ T365] Code: 89 c6 e8 d4 b7 0d ff 90 0f 0b 90 90 31 c0 e9 31 ff ff ff 90 48 c7 c7 e0 a0 22 9f 48 89 f2 48 89 c1 4c 89 c6 e8 b2 b7 0d ff 90 <0f> 0b 90 90 31 c0 e9 0f ff ff ff 48 89 f7 48 89 44 24 10 4c 89 44 +... +[ 59.288812][ T365] Call Trace: +[ 59.289056][ T365] +[ 59.289224][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.289546][ T365] ets_qdisc_change+0xd2b/0x1e80 +[ 59.289891][ T365] ? __lock_acquire+0x7e7/0x1be0 +[ 59.290223][ T365] ? __pfx_ets_qdisc_change+0x10/0x10 +[ 59.290546][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.290898][ T365] ? __mutex_trylock_common+0xda/0x240 +[ 59.291228][ T365] ? __pfx___mutex_trylock_common+0x10/0x10 +[ 59.291655][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.291993][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.292313][ T365] ? trace_contention_end+0xc8/0x110 +[ 59.292656][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293022][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293351][ T365] tc_modify_qdisc+0x63a/0x1cf0 + +Fix this by always checking and removing an ets class from the active list +when changing it to strict. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/net/sched/sch_ets.c?id=ce052b9402e461a9aded599f5b47e76bc727f7de#n663 + +Fixes: cd9b50adc6bb9 ("net/sched: ets: fix crash when flipping from 'strict' to 'quantum'") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Reviewed-by: Petr Machata +Link: https://patch.msgid.link/20251208190125.1868423-1-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index ae46643e596d3..306e046276d46 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -664,6 +664,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nstrict; i < nstrict; i++) { ++ if (cl_is_active(&q->classes[i])) ++ list_del_init(&q->classes[i].alist); ++ } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + +-- +2.51.0 + diff --git a/queue-6.18/net-ti-icssg-prueth-add-ptp_1588_clock_optional-depe.patch b/queue-6.18/net-ti-icssg-prueth-add-ptp_1588_clock_optional-depe.patch new file mode 100644 index 0000000000..9493455044 --- /dev/null +++ b/queue-6.18/net-ti-icssg-prueth-add-ptp_1588_clock_optional-depe.patch @@ -0,0 +1,55 @@ +From 6ed8fe45a42be35aae6ea10b1e22ed99e21b8348 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:01:28 +0100 +Subject: net: ti: icssg-prueth: add PTP_1588_CLOCK_OPTIONAL dependency + +From: Arnd Bergmann + +[ Upstream commit 9e7477a427449a8a3cd00c188e20a880e3d94638 ] + +The new icssg-prueth driver needs the same dependency as the other parts +that use the ptp-1588: + +WARNING: unmet direct dependencies detected for TI_ICSS_IEP + Depends on [m]: NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_TI [=y] && PTP_1588_CLOCK_OPTIONAL [=m] && TI_PRUSS [=y] + Selected by [y]: + - TI_PRUETH [=y] && NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_TI [=y] && PRU_REMOTEPROC [=y] && NET_SWITCHDEV [=y] + +Add the correct dependency on the two drivers missing it, and remove +the pointless 'imply' in the process. + +Fixes: e654b85a693e ("net: ti: icssg-prueth: Add ICSSG Ethernet driver for AM65x SR1.0 platforms") +Fixes: 511f6c1ae093 ("net: ti: icssm-prueth: Adds ICSSM Ethernet driver") +Signed-off-by: Arnd Bergmann +Reviewed-by: Vadim Fedorenko +Link: https://patch.msgid.link/20251204100138.1034175-1-arnd@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/Kconfig | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig +index a54d71155263c..fe5b2926d8ab0 100644 +--- a/drivers/net/ethernet/ti/Kconfig ++++ b/drivers/net/ethernet/ti/Kconfig +@@ -209,6 +209,7 @@ config TI_ICSSG_PRUETH_SR1 + depends on PRU_REMOTEPROC + depends on NET_SWITCHDEV + depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER ++ depends on PTP_1588_CLOCK_OPTIONAL + help + Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem. + This subsystem is available on the AM65 SR1.0 platform. +@@ -234,7 +235,7 @@ config TI_PRUETH + depends on PRU_REMOTEPROC + depends on NET_SWITCHDEV + select TI_ICSS_IEP +- imply PTP_1588_CLOCK ++ depends on PTP_1588_CLOCK_OPTIONAL + help + Some TI SoCs has Programmable Realtime Unit (PRU) cores which can + support Single or Dual Ethernet ports with the help of firmware code +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch b/queue-6.18/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch new file mode 100644 index 0000000000..d24ddd0a74 --- /dev/null +++ b/queue-6.18/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch @@ -0,0 +1,90 @@ +From 17f3c6a36d5a32eb18719cab7a05e6a047dace18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 12:58:01 +0100 +Subject: netfilter: nf_conncount: fix leaked ct in error paths + +From: Fernando Fernandez Mancera + +[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ] + +There are some situations where ct might be leaked as error paths are +skipping the refcounted check and return immediately. In order to solve +it make sure that the check is always called. + +Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conncount.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index b84cfb5616df4..3c1b155f7a0ea 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net, + struct nf_conn *found_ct; + unsigned int collect = 0; + bool refcounted = false; ++ int err = 0; + + if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- if (refcounted) +- nf_ct_put(ct); +- return -EEXIST; ++ err = -EEXIST; ++ goto out_put; + } + + if ((u32)jiffies == list->last_gc) +@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net, + } + + add_new_node: +- if (WARN_ON_ONCE(list->count > INT_MAX)) +- return -EOVERFLOW; ++ if (WARN_ON_ONCE(list->count > INT_MAX)) { ++ err = -EOVERFLOW; ++ goto out_put; ++ } + + conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); +- if (conn == NULL) +- return -ENOMEM; ++ if (conn == NULL) { ++ err = -ENOMEM; ++ goto out_put; ++ } + + conn->tuple = tuple; + conn->zone = *zone; +@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net, + out_put: + if (refcounted) + nf_ct_put(ct); +- return 0; ++ return err; + } + + int nf_conncount_add_skb(struct net *net, +@@ -446,11 +450,10 @@ insert_tree(struct net *net, + + rb_link_node_rcu(&rbconn->node, parent, rbnode); + rb_insert_color(&rbconn->node, root); +- +- if (refcounted) +- nf_ct_put(ct); + } + out_unlock: ++ if (refcounted) ++ nf_ct_put(ct); + spin_unlock_bh(&nf_conncount_locks[hash]); + return count; + } +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nf_nat-remove-bogus-direction-check.patch b/queue-6.18/netfilter-nf_nat-remove-bogus-direction-check.patch new file mode 100644 index 0000000000..bb259e65fe --- /dev/null +++ b/queue-6.18/netfilter-nf_nat-remove-bogus-direction-check.patch @@ -0,0 +1,129 @@ +From fd6e7e2a2d434f8da34ba840707b2d5345881fcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:00:34 +0100 +Subject: netfilter: nf_nat: remove bogus direction check + +From: Florian Westphal + +[ Upstream commit 5ec8ca26fe93103577c904644b0957f069d0051a ] + +Jakub reports spurious failures of the 'conntrack_reverse_clash.sh' +selftest. A bogus test makes nat core resort to port rewrite even +though there is no need for this. + +When the test is made, nf_nat_used_tuple() would already have caused us +to return if no other CPU had added a colliding entry. +Moreover, nf_nat_used_tuple() would have ignored the colliding entry if +their origin tuples had been the same. + +All that is left to check is if the colliding entry in the hash table +is subject to NAT, and, if its not, if our entry matches in the reverse +direction, e.g. hash table has + +addr1:1234 -> addr2:80, and we want to commit +addr2:80 -> addr1:1234. + +Because we already checked that neither the new nor the committed entry is +subject to NAT we only have to check origin vs. reply tuple: +for non-nat entries, the reply tuple is always the inverted original. + +Just in case there are more problems extend the error reporting +in the selftest while at it and dump conntrack table/stats on error. + +Reported-by: Jakub Kicinski +Closes: https://lore.kernel.org/netdev/20251206175135.4a56591b@kernel.org/ +Fixes: d8f84a9bc7c4 ("netfilter: nf_nat: don't try nat source port reallocation for reverse dir clash") +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_nat_core.c | 14 +------------- + .../net/netfilter/conntrack_reverse_clash.c | 13 +++++++++---- + .../net/netfilter/conntrack_reverse_clash.sh | 2 ++ + 3 files changed, 12 insertions(+), 17 deletions(-) + +diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c +index 78a61dac4ade8..e6b24586d2fed 100644 +--- a/net/netfilter/nf_nat_core.c ++++ b/net/netfilter/nf_nat_core.c +@@ -294,25 +294,13 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple, + + ct = nf_ct_tuplehash_to_ctrack(thash); + +- /* NB: IP_CT_DIR_ORIGINAL should be impossible because +- * nf_nat_used_tuple() handles origin collisions. +- * +- * Handle remote chance other CPU confirmed its ct right after. +- */ +- if (thash->tuple.dst.dir != IP_CT_DIR_REPLY) +- goto out; +- + /* clashing connection subject to NAT? Retry with new tuple. */ + if (READ_ONCE(ct->status) & uses_nat) + goto out; + + if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, +- &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple) && +- nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, +- &ignored_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) { ++ &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple)) + taken = false; +- goto out; +- } + out: + nf_ct_put(ct); + return taken; +diff --git a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c +index 507930cee8cb6..462d628cc3bdb 100644 +--- a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c ++++ b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c +@@ -33,9 +33,14 @@ static void die(const char *e) + exit(111); + } + +-static void die_port(uint16_t got, uint16_t want) ++static void die_port(const struct sockaddr_in *sin, uint16_t want) + { +- fprintf(stderr, "Port number changed, wanted %d got %d\n", want, ntohs(got)); ++ uint16_t got = ntohs(sin->sin_port); ++ char str[INET_ADDRSTRLEN]; ++ ++ inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)); ++ ++ fprintf(stderr, "Port number changed, wanted %d got %d from %s\n", want, got, str); + exit(1); + } + +@@ -100,7 +105,7 @@ int main(int argc, char *argv[]) + die("child recvfrom"); + + if (peer.sin_port != htons(PORT)) +- die_port(peer.sin_port, PORT); ++ die_port(&peer, PORT); + } else { + if (sendto(s2, buf, LEN, 0, (struct sockaddr *)&sa1, sizeof(sa1)) != LEN) + continue; +@@ -109,7 +114,7 @@ int main(int argc, char *argv[]) + die("parent recvfrom"); + + if (peer.sin_port != htons((PORT + 1))) +- die_port(peer.sin_port, PORT + 1); ++ die_port(&peer, PORT + 1); + } + } + +diff --git a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh +index a24c896347a88..dc7e9d6da0624 100755 +--- a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh ++++ b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh +@@ -45,6 +45,8 @@ if ip netns exec "$ns0" ./conntrack_reverse_clash; then + echo "PASS: No SNAT performed for null bindings" + else + echo "ERROR: SNAT performed without any matching snat rule" ++ ip netns exec "$ns0" conntrack -L ++ ip netns exec "$ns0" conntrack -S + exit 1 + fi + +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nf_tables-remove-redundant-chain-validatio.patch b/queue-6.18/netfilter-nf_tables-remove-redundant-chain-validatio.patch new file mode 100644 index 0000000000..c7e3bfb696 --- /dev/null +++ b/queue-6.18/netfilter-nf_tables-remove-redundant-chain-validatio.patch @@ -0,0 +1,59 @@ +From c03f4545f4164b898ad793aaa728d9b0f11ca4eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Nov 2025 13:42:05 +0100 +Subject: netfilter: nf_tables: remove redundant chain validation on register + store + +From: Pablo Neira Ayuso + +[ Upstream commit a67fd55f6a09f4119b7232c19e0f348fe31ab0db ] + +This validation predates the introduction of the state machine that +determines when to enter slow path validation for error reporting. + +Currently, table validation is perform when: + +- new rule contains expressions that need validation. +- new set element with jump/goto verdict. + +Validation on register store skips most checks with no basechains, still +this walks the graph searching for loops and ensuring expressions are +called from the right hook. Remove this. + +Fixes: a654de8fdc18 ("netfilter: nf_tables: fix chain dependency validation") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index eed434e0a9702..1a204f6371ad1 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -11678,21 +11678,10 @@ static int nft_validate_register_store(const struct nft_ctx *ctx, + enum nft_data_types type, + unsigned int len) + { +- int err; +- + switch (reg) { + case NFT_REG_VERDICT: + if (type != NFT_DATA_VERDICT) + return -EINVAL; +- +- if (data != NULL && +- (data->verdict.code == NFT_GOTO || +- data->verdict.code == NFT_JUMP)) { +- err = nft_chain_validate(ctx, data->verdict.chain); +- if (err < 0) +- return err; +- } +- + break; + default: + if (type != NFT_DATA_VALUE) +-- +2.51.0 + diff --git a/queue-6.18/netrom-fix-memory-leak-in-nr_sendmsg.patch b/queue-6.18/netrom-fix-memory-leak-in-nr_sendmsg.patch new file mode 100644 index 0000000000..d4a06cbab5 --- /dev/null +++ b/queue-6.18/netrom-fix-memory-leak-in-nr_sendmsg.patch @@ -0,0 +1,74 @@ +From 7dbd3be06f02e7890c7778e61ea2e7988349049f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 12:13:15 +0800 +Subject: netrom: Fix memory leak in nr_sendmsg() + +From: Wang Liang + +[ Upstream commit 613d12dd794e078be8ff3cf6b62a6b9acf7f4619 ] + +syzbot reported a memory leak [1]. + +When function sock_alloc_send_skb() return NULL in nr_output(), the +original skb is not freed, which was allocated in nr_sendmsg(). Fix this +by freeing it before return. + +[1] +BUG: memory leak +unreferenced object 0xffff888129f35500 (size 240): + comm "syz.0.17", pid 6119, jiffies 4294944652 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 10 52 28 81 88 ff ff ..........R(.... + backtrace (crc 1456a3e4): + kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline] + slab_post_alloc_hook mm/slub.c:4983 [inline] + slab_alloc_node mm/slub.c:5288 [inline] + kmem_cache_alloc_node_noprof+0x36f/0x5e0 mm/slub.c:5340 + __alloc_skb+0x203/0x240 net/core/skbuff.c:660 + alloc_skb include/linux/skbuff.h:1383 [inline] + alloc_skb_with_frags+0x69/0x3f0 net/core/skbuff.c:6671 + sock_alloc_send_pskb+0x379/0x3e0 net/core/sock.c:2965 + sock_alloc_send_skb include/net/sock.h:1859 [inline] + nr_sendmsg+0x287/0x450 net/netrom/af_netrom.c:1105 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg net/socket.c:742 [inline] + sock_write_iter+0x293/0x2a0 net/socket.c:1195 + new_sync_write fs/read_write.c:593 [inline] + vfs_write+0x45d/0x710 fs/read_write.c:686 + ksys_write+0x143/0x170 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xa4/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7abc36bbbb6d7d40b58 +Tested-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20251129041315.1550766-1-wangliang74@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_out.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 5e531394a724b..2b3cbceb0b52d 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) + frontlen = skb_headroom(skb); + + while (skb->len > 0) { +- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) ++ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) { ++ kfree_skb(skb); + return; ++ } + + skb_reserve(skbn, frontlen); + +-- +2.51.0 + diff --git a/queue-6.18/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch b/queue-6.18/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch new file mode 100644 index 0000000000..c3171ee4f3 --- /dev/null +++ b/queue-6.18/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch @@ -0,0 +1,37 @@ +From 0ed33f78f905e0fee357441c7f5dfe71c9956206 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 09:56:39 +0300 +Subject: nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() + +From: Dan Carpenter + +[ Upstream commit 885bebac9909994050bbbeed0829c727e42bd1b7 ] + +Set the error code if "transferred != sizeof(cmd)" instead of +returning success. + +Fixes: dbafc28955fa ("NFC: pn533: don't send USB data off of the stack") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aTfIJ9tZPmeUF4W1@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c +index ffd7367ce1194..018a80674f06e 100644 +--- a/drivers/nfc/pn533/usb.c ++++ b/drivers/nfc/pn533/usb.c +@@ -406,7 +406,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) + if (rc || (transferred != sizeof(cmd))) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); +- return rc; ++ return rc ?: -EINVAL; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); +-- +2.51.0 + diff --git a/queue-6.18/selftest-af_unix-support-compilers-without-flex-arra.patch b/queue-6.18/selftest-af_unix-support-compilers-without-flex-arra.patch new file mode 100644 index 0000000000..ebb8ffdb60 --- /dev/null +++ b/queue-6.18/selftest-af_unix-support-compilers-without-flex-arra.patch @@ -0,0 +1,47 @@ +From da0e3f60cd2f70e2a06414ffd03bc09adb0a612a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 09:10:00 -0800 +Subject: selftest: af_unix: Support compilers without + flex-array-member-not-at-end support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Guenter Roeck + +[ Upstream commit 06f7cae92fe346fa49a8a9b161124b26cc5c3ed1 ] + +Fix: + +gcc: error: unrecognized command-line option ‘-Wflex-array-member-not-at-end’ + +by making the compiler option dependent on its support. + +Fixes: 1838731f1072c ("selftest: af_unix: Add -Wall and -Wflex-array-member-not-at-end to CFLAGS.") +Cc: Kuniyuki Iwashima +Signed-off-by: Guenter Roeck +Link: https://patch.msgid.link/20251205171010.515236-7-linux@roeck-us.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/Makefile | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/af_unix/Makefile b/tools/testing/selftests/net/af_unix/Makefile +index 528d14c598bb5..2889403e35468 100644 +--- a/tools/testing/selftests/net/af_unix/Makefile ++++ b/tools/testing/selftests/net/af_unix/Makefile +@@ -1,4 +1,9 @@ +-CFLAGS += $(KHDR_INCLUDES) -Wall -Wflex-array-member-not-at-end ++top_srcdir := ../../../../.. ++include $(top_srcdir)/scripts/Makefile.compiler ++ ++cc-option = $(call __cc-option, $(CC),,$(1),$(2)) ++ ++CFLAGS += $(KHDR_INCLUDES) -Wall $(call cc-option,-Wflex-array-member-not-at-end) + + TEST_GEN_PROGS := \ + diag_uid \ +-- +2.51.0 + diff --git a/queue-6.18/selftests-net-fix-build-warnings.patch b/queue-6.18/selftests-net-fix-build-warnings.patch new file mode 100644 index 0000000000..c4208018c6 --- /dev/null +++ b/queue-6.18/selftests-net-fix-build-warnings.patch @@ -0,0 +1,60 @@ +From d897ed1a38c1c3aab5590fd1bafa8506c105a33d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 09:10:04 -0800 +Subject: selftests: net: Fix build warnings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Guenter Roeck + +[ Upstream commit 59546e874403c1dd0cbc42df06fdf8c113f72022 ] + +Fix + +ksft.h: In function ‘ksft_ready’: +ksft.h:27:9: warning: ignoring return value of ‘write’ declared with attribute ‘warn_unused_result’ + +ksft.h: In function ‘ksft_wait’: +ksft.h:51:9: warning: ignoring return value of ‘read’ declared with attribute ‘warn_unused_result’ + +by checking the return value of the affected functions and displaying +an error message if an error is seen. + +Fixes: 2b6d490b82668 ("selftests: drv-net: Factor out ksft C helpers") +Cc: Joe Damato +Signed-off-by: Guenter Roeck +Link: https://patch.msgid.link/20251205171010.515236-11-linux@roeck-us.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/lib/ksft.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/net/lib/ksft.h b/tools/testing/selftests/net/lib/ksft.h +index 17dc34a612c64..03912902a6d30 100644 +--- a/tools/testing/selftests/net/lib/ksft.h ++++ b/tools/testing/selftests/net/lib/ksft.h +@@ -24,7 +24,8 @@ static inline void ksft_ready(void) + fd = STDOUT_FILENO; + } + +- write(fd, msg, sizeof(msg)); ++ if (write(fd, msg, sizeof(msg)) < 0) ++ perror("write()"); + if (fd != STDOUT_FILENO) + close(fd); + } +@@ -48,7 +49,8 @@ static inline void ksft_wait(void) + fd = STDIN_FILENO; + } + +- read(fd, &byte, sizeof(byte)); ++ if (read(fd, &byte, sizeof(byte)) < 0) ++ perror("read()"); + if (fd != STDIN_FILENO) + close(fd); + } +-- +2.51.0 + diff --git a/queue-6.18/selftests-net-tfo-fix-build-warning.patch b/queue-6.18/selftests-net-tfo-fix-build-warning.patch new file mode 100644 index 0000000000..dd237750a4 --- /dev/null +++ b/queue-6.18/selftests-net-tfo-fix-build-warning.patch @@ -0,0 +1,47 @@ +From 66d8659b9d7c89b53201c23e854900a9d7ebf360 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 09:10:07 -0800 +Subject: selftests: net: tfo: Fix build warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Guenter Roeck + +[ Upstream commit 91dc09a609d9443e6b34bdb355a18d579a95e132 ] + +Fix + +tfo.c: In function ‘run_server’: +tfo.c:84:9: warning: ignoring return value of ‘read’ declared with attribute ‘warn_unused_result’ + +by evaluating the return value from read() and displaying an error message +if it reports an error. + +Fixes: c65b5bb2329e3 ("selftests: net: add passive TFO test binary") +Cc: David Wei +Signed-off-by: Guenter Roeck +Link: https://patch.msgid.link/20251205171010.515236-14-linux@roeck-us.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/tfo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/tfo.c b/tools/testing/selftests/net/tfo.c +index eb3cac5e583c9..8d82140f0f767 100644 +--- a/tools/testing/selftests/net/tfo.c ++++ b/tools/testing/selftests/net/tfo.c +@@ -81,7 +81,8 @@ static void run_server(void) + if (getsockopt(connfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &opt, &len) < 0) + error(1, errno, "getsockopt(SO_INCOMING_NAPI_ID)"); + +- read(connfd, buf, 64); ++ if (read(connfd, buf, 64) < 0) ++ perror("read()"); + fprintf(outfile, "%d\n", opt); + + fclose(outfile); +-- +2.51.0 + diff --git a/queue-6.18/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch b/queue-6.18/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch new file mode 100644 index 0000000000..3dd6fbe0f8 --- /dev/null +++ b/queue-6.18/selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch @@ -0,0 +1,41 @@ +From 80162dffdc5131f775d19955090ffc5007f6690b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 13:16:49 +0100 +Subject: selftests: netfilter: packetdrill: avoid failure on HZ=100 kernel + +From: Florian Westphal + +[ Upstream commit fec7b0795548b43e2c3c46e3143c34ef6070341c ] + +packetdrill --ip_version=ipv4 --mtu=1500 --tolerance_usecs=1000000 --non_fatal packet conntrack_syn_challenge_ack.pkt +conntrack v1.4.8 (conntrack-tools): 1 flow entries have been shown. +conntrack_syn_challenge_ack.pkt:32: error executing `conntrack -f $NFCT_IP_VERSION \ +-L -p tcp --dport 8080 | grep UNREPLIED | grep -q SYN_SENT` command: non-zero status 1 + +Affected kernel had CONFIG_HZ=100; reset packet was still sitting in +backlog. + +Reported-by: Yi Chen +Fixes: a8a388c2aae4 ("selftests: netfilter: add packetdrill based conntrack tests") +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + .../net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt b/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt +index 3442cd29bc932..cdb3910af95b4 100644 +--- a/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt ++++ b/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt +@@ -26,7 +26,7 @@ + + +0.01 > R 643160523:643160523(0) win 0 + +-+0.01 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT` +++0.1 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT` + + // Must go through. + +0.01 > S 0:0(0) win 65535 +-- +2.51.0 + diff --git a/queue-6.18/selftests-netfilter-prefer-xfail-in-case-race-wasn-t.patch b/queue-6.18/selftests-netfilter-prefer-xfail-in-case-race-wasn-t.patch new file mode 100644 index 0000000000..c71c20d8df --- /dev/null +++ b/queue-6.18/selftests-netfilter-prefer-xfail-in-case-race-wasn-t.patch @@ -0,0 +1,65 @@ +From 20c56dc0efa322716621492de3baac6cfe5c186a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 00:03:36 +0100 +Subject: selftests: netfilter: prefer xfail in case race wasn't triggered + +From: Florian Westphal + +[ Upstream commit b8a81b0ce539e021ac72825238aea1eb657000f0 ] + +Jakub says: "We try to reserve SKIP for tests skipped because tool is +missing in env, something isn't built into the kernel etc." + +use xfail, we can't force the race condition to appear at will +so its expected that the test 'fails' occasionally. + +Fixes: 78a588363587 ("selftests: netfilter: add conntrack clash resolution test case") +Reported-by: Jakub Kicinski +Closes: https://lore.kernel.org/netdev/20251206175647.5c32f419@kernel.org/ +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/netfilter/conntrack_clash.sh | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/net/netfilter/conntrack_clash.sh b/tools/testing/selftests/net/netfilter/conntrack_clash.sh +index 7fc6c5dbd5516..84b8eb12143ae 100755 +--- a/tools/testing/selftests/net/netfilter/conntrack_clash.sh ++++ b/tools/testing/selftests/net/netfilter/conntrack_clash.sh +@@ -116,7 +116,7 @@ run_one_clash_test() + # not a failure: clash resolution logic did not trigger. + # With right timing, xmit completed sequentially and + # no parallel insertion occurs. +- return $ksft_skip ++ return $ksft_xfail + } + + run_clash_test() +@@ -133,12 +133,12 @@ run_clash_test() + if [ $rv -eq 0 ];then + echo "PASS: clash resolution test for $daddr:$dport on attempt $i" + return 0 +- elif [ $rv -eq $ksft_skip ]; then ++ elif [ $rv -eq $ksft_xfail ]; then + softerr=1 + fi + done + +- [ $softerr -eq 1 ] && echo "SKIP: clash resolution for $daddr:$dport did not trigger" ++ [ $softerr -eq 1 ] && echo "XFAIL: clash resolution for $daddr:$dport did not trigger" + } + + ip link add veth0 netns "$nsclient1" type veth peer name veth0 netns "$nsrouter" +@@ -167,8 +167,7 @@ load_simple_ruleset "$nsclient2" + run_clash_test "$nsclient2" "$nsclient2" 127.0.0.1 9001 + + if [ $clash_resolution_active -eq 0 ];then +- [ "$ret" -eq 0 ] && ret=$ksft_skip +- echo "SKIP: Clash resolution did not trigger" ++ [ "$ret" -eq 0 ] && ret=$ksft_xfail + fi + + exit $ret +-- +2.51.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 3b072faff5..e9f37a5879 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -50,3 +50,55 @@ bluetooth-btusb-add-new-custom-firmwares.patch bluetooth-btusb-add-new-vid-pid-13d3-3533-for-rtl882.patch bluetooth-btusb-add-new-vid-pid-0x0489-0xe12f-for-rt.patch gfs2-fix-use-of-bio_chain.patch +net-fec-err007885-workaround-for-xdp-tx-path.patch +netrom-fix-memory-leak-in-nr_sendmsg.patch +net-sched-ets-always-remove-class-from-active-list-b.patch +net-mlx5-make-enable_mpesw-idempotent.patch +net-mlx5e-avoid-unregistering-psp-twice.patch +net-phy-realtek-eliminate-priv-phycr2-variable.patch +net-phy-realtek-eliminate-has_phycr2-variable.patch +net-phy-realtek-allow-clkout-to-be-disabled-on-rtl82.patch +net-phy-realtek-eliminate-priv-phycr1-variable.patch +net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch +net-phy-rtl8211fvd-restore-disabling-of-phy-mode-eee.patch +ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch +net-mlx5-fix-double-unregister-of-hca_ports-componen.patch +mlxsw-spectrum_router-fix-possible-neighbour-referen.patch +mlxsw-spectrum_router-fix-neighbour-use-after-free.patch +mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch +bnxt_en-fix-xdp_tx-path.patch +net-openvswitch-fix-middle-attribute-validation-in-p.patch +net-ti-icssg-prueth-add-ptp_1588_clock_optional-depe.patch +broadcom-b44-prevent-uninitialized-value-usage.patch +selftest-af_unix-support-compilers-without-flex-arra.patch +selftests-net-fix-build-warnings.patch +selftests-net-tfo-fix-build-warning.patch +inet-frags-avoid-theoretical-race-in-ip_frag_reinit.patch +inet-frags-add-inet_frag_queue_flush.patch +inet-frags-flush-pending-skbs-in-fqdir_pre_exit.patch +netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch +ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch +selftests-netfilter-prefer-xfail-in-case-race-wasn-t.patch +caif-fix-integer-underflow-in-cffrml_receive.patch +net-sched-ets-remove-drr-class-from-the-active-list-.patch +nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch +netfilter-nf_nat-remove-bogus-direction-check.patch +netfilter-nf_tables-remove-redundant-chain-validatio.patch +selftests-netfilter-packetdrill-avoid-failure-on-hz-.patch +iommufd-selftest-make-it-clearer-to-gcc-that-the-acc.patch +iommufd-selftest-check-for-overflow-in-iommu_test_op.patch +can-j1939-make-j1939_sk_bind-fail-if-device-is-no-lo.patch +ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch +net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch +net-mlx5-drain-firmware-reset-in-shutdown-callback.patch +net-mlx5-fw_tracer-validate-format-string-parameters.patch +net-mlx5-fw_tracer-handle-escaped-percent-properly.patch +net-mlx5-serialize-firmware-reset-with-devlink.patch +net-mlx5e-use-ip6_dst_lookup-instead-of-ipv6_dst_loo.patch +net-mlx5e-trigger-neighbor-resolution-for-unresolved.patch +net-mlx5e-don-t-include-psp-in-the-hard-mtu-calculat.patch +net-handshake-duplicate-handshake-cancellations-leak.patch +net-enetc-do-not-transmit-redirected-xdp-frames-when.patch +net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch +net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch +net-hns3-add-vlan-id-validation-before-using.patch diff --git a/queue-6.6/broadcom-b44-prevent-uninitialized-value-usage.patch b/queue-6.6/broadcom-b44-prevent-uninitialized-value-usage.patch new file mode 100644 index 0000000000..4122bdf173 --- /dev/null +++ b/queue-6.6/broadcom-b44-prevent-uninitialized-value-usage.patch @@ -0,0 +1,45 @@ +From dbdb7f9402561de49b81f53cced31105efbcce9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 18:58:16 +0300 +Subject: broadcom: b44: prevent uninitialized value usage + +From: Alexey Simakov + +[ Upstream commit 50b3db3e11864cb4e18ff099cfb38e11e7f87a68 ] + +On execution path with raised B44_FLAG_EXTERNAL_PHY, b44_readphy() +leaves bmcr value uninitialized and it is used later in the code. + +Add check of this flag at the beginning of the b44_nway_reset() and +exit early of the function with restarting autonegotiation if an +external PHY is used. + +Fixes: 753f492093da ("[B44]: port to native ssb support") +Reviewed-by: Jonas Gorski +Reviewed-by: Andrew Lunn +Signed-off-by: Alexey Simakov +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20251205155815.4348-1-bigalex934@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/b44.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c +index 1be6d14030bcf..ba40549536e46 100644 +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -1789,6 +1789,9 @@ static int b44_nway_reset(struct net_device *dev) + u32 bmcr; + int r; + ++ if (bp->flags & B44_FLAG_EXTERNAL_PHY) ++ return phy_ethtool_nway_reset(dev); ++ + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); +-- +2.51.0 + diff --git a/queue-6.6/caif-fix-integer-underflow-in-cffrml_receive.patch b/queue-6.6/caif-fix-integer-underflow-in-cffrml_receive.patch new file mode 100644 index 0000000000..7f0f51e2ec --- /dev/null +++ b/queue-6.6/caif-fix-integer-underflow-in-cffrml_receive.patch @@ -0,0 +1,58 @@ +From 13db93c3f2a0758fbf8acf6ce3217c7446e11f1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 21:30:47 +0800 +Subject: caif: fix integer underflow in cffrml_receive() + +From: Junrui Luo + +[ Upstream commit 8a11ff0948b5ad09b71896b7ccc850625f9878d1 ] + +The cffrml_receive() function extracts a length field from the packet +header and, when FCS is disabled, subtracts 2 from this length without +validating that len >= 2. + +If an attacker sends a malicious packet with a length field of 0 or 1 +to an interface with FCS disabled, the subtraction causes an integer +underflow. + +This can lead to memory exhaustion and kernel instability, potential +information disclosure if padding contains uninitialized kernel memory. + +Fix this by validating that len >= 2 before performing the subtraction. + +Reported-by: Yuhao Jiang +Reported-by: Junrui Luo +Fixes: b482cd2053e3 ("net-caif: add CAIF core protocol stack") +Signed-off-by: Junrui Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/SYBPR01MB7881511122BAFEA8212A1608AFA6A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/caif/cffrml.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c +index 6651a8dc62e04..d4d63586053ad 100644 +--- a/net/caif/cffrml.c ++++ b/net/caif/cffrml.c +@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) + len = le16_to_cpu(tmp); + + /* Subtract for FCS on length if FCS is not used. */ +- if (!this->dofcs) ++ if (!this->dofcs) { ++ if (len < 2) { ++ ++cffrml_rcv_error; ++ pr_err("Invalid frame length (%d)\n", len); ++ cfpkt_destroy(pkt); ++ return -EPROTO; ++ } + len -= 2; ++ } + + if (cfpkt_setlen(pkt, len) < 0) { + ++cffrml_rcv_error; +-- +2.51.0 + diff --git a/queue-6.6/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch b/queue-6.6/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch new file mode 100644 index 0000000000..2238b30c96 --- /dev/null +++ b/queue-6.6/ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch @@ -0,0 +1,159 @@ +From 79b4283e36464d7f138bacb05f4eff4716017866 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 14:19:01 +0200 +Subject: ethtool: Avoid overflowing userspace buffer on stats query + +From: Gal Pressman + +[ Upstream commit 7b07be1ff1cb6c49869910518650e8d0abc7d25f ] + +The ethtool -S command operates across three ioctl calls: +ETHTOOL_GSSET_INFO for the size, ETHTOOL_GSTRINGS for the names, and +ETHTOOL_GSTATS for the values. + +If the number of stats changes between these calls (e.g., due to device +reconfiguration), userspace's buffer allocation will be incorrect, +potentially leading to buffer overflow. + +Drivers are generally expected to maintain stable stat counts, but some +drivers (e.g., mlx5, bnx2x, bna, ksz884x) use dynamic counters, making +this scenario possible. + +Some drivers try to handle this internally: +- bnad_get_ethtool_stats() returns early in case stats.n_stats is not + equal to the driver's stats count. +- micrel/ksz884x also makes sure not to write anything beyond + stats.n_stats and overflow the buffer. + +However, both use stats.n_stats which is already assigned with the value +returned from get_sset_count(), hence won't solve the issue described +here. + +Change ethtool_get_strings(), ethtool_get_stats(), +ethtool_get_phy_stats() to not return anything in case of a mismatch +between userspace's size and get_sset_size(), to prevent buffer +overflow. +The returned n_stats value will be equal to zero, to reflect that +nothing has been returned. + +This could result in one of two cases when using upstream ethtool, +depending on when the size change is detected: +1. When detected in ethtool_get_strings(): + # ethtool -S eth2 + no stats available + +2. When detected in get stats, all stats will be reported as zero. + +Both cases are presumably transient, and a subsequent ethtool call +should succeed. + +Other than the overflow avoidance, these two cases are very evident (no +output/cleared stats), which is arguably better than presenting +incorrect/shifted stats. +I also considered returning an error instead of a "silent" response, but +that seems more destructive towards userspace apps. + +Notes: +- This patch does not claim to fix the inherent race, it only makes sure + that we do not overflow the userspace buffer, and makes for a more + predictable behavior. + +- RTNL lock is held during each ioctl, the race window exists between + the separate ioctl calls when the lock is released. + +- Userspace ethtool always fills stats.n_stats, but it is likely that + these stats ioctls are implemented in other userspace applications + which might not fill it. The added code checks that it's not zero, + to prevent any regressions. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Dragos Tatulea +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Link: https://patch.msgid.link/20251208121901.3203692-1-gal@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 4486cbe2faf0c..eaeb514b7e5f6 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1955,7 +1955,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + return -ENOMEM; + WARN_ON_ONCE(!ret); + +- gstrings.len = ret; ++ if (gstrings.len && gstrings.len != ret) ++ gstrings.len = 0; ++ else ++ gstrings.len = ret; + + if (gstrings.len) { + data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); +@@ -2070,10 +2073,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + +- stats.n_stats = n_stats; ++ if (stats.n_stats && stats.n_stats != n_stats) ++ stats.n_stats = 0; ++ else ++ stats.n_stats = n_stats; + +- if (n_stats) { +- data = vzalloc(array_size(n_stats, sizeof(u64))); ++ if (stats.n_stats) { ++ data = vzalloc(array_size(stats.n_stats, sizeof(u64))); + if (!data) + return -ENOMEM; + ops->get_ethtool_stats(dev, &stats, data); +@@ -2085,7 +2091,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); +- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + goto out; + ret = 0; + +@@ -2121,6 +2129,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev, + return -EOPNOTSUPP; + + n_stats = phy_ops->get_sset_count(phydev); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2141,6 +2153,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev, + return -EOPNOTSUPP; + + n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); ++ if (stats->n_stats && stats->n_stats != n_stats) { ++ stats->n_stats = 0; ++ return 0; ++ } + + ret = ethtool_vzalloc_stats_array(n_stats, data); + if (ret) +@@ -2177,7 +2193,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) + } + + useraddr += sizeof(stats); +- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) ++ if (stats.n_stats && ++ copy_to_user(useraddr, data, ++ array_size(stats.n_stats, sizeof(u64)))) + ret = -EFAULT; + + out: +-- +2.51.0 + diff --git a/queue-6.6/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch b/queue-6.6/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch new file mode 100644 index 0000000000..99f2d0777f --- /dev/null +++ b/queue-6.6/iommufd-selftest-check-for-overflow-in-iommu_test_op.patch @@ -0,0 +1,57 @@ +From bdc13c0547c15a75bdeb923fa47f38a877cf8b64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Dec 2025 11:53:40 -0400 +Subject: iommufd/selftest: Check for overflow in IOMMU_TEST_OP_ADD_RESERVED + +From: Jason Gunthorpe + +[ Upstream commit e6a973af11135439de32ece3b9cbe3bfc043bea8 ] + +syzkaller found it could overflow math in the test infrastructure and +cause a WARN_ON by corrupting the reserved interval tree. This only +effects test kernels with CONFIG_IOMMUFD_TEST. + +Validate the user input length in the test ioctl. + +Fixes: f4b20bb34c83 ("iommufd: Add kernel support for testing iommufd") +Link: https://patch.msgid.link/r/0-v1-cd99f6049ba5+51-iommufd_syz_add_resv_jgg@nvidia.com +Reviewed-by: Samiullah Khawaja +Reviewed-by: Kevin Tian +Tested-by: Yi Liu +Reported-by: syzbot+57fdb0cf6a0c5d1f15a2@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/69368129.a70a0220.38f243.008f.GAE@google.com +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/selftest.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c +index 00b794d74e03b..8025ff65ed4de 100644 +--- a/drivers/iommu/iommufd/selftest.c ++++ b/drivers/iommu/iommufd/selftest.c +@@ -512,14 +512,20 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd, + unsigned int mockpt_id, + unsigned long start, size_t length) + { ++ unsigned long last; + struct iommufd_ioas *ioas; + int rc; + ++ if (!length) ++ return -EINVAL; ++ if (check_add_overflow(start, length - 1, &last)) ++ return -EOVERFLOW; ++ + ioas = iommufd_get_ioas(ucmd->ictx, mockpt_id); + if (IS_ERR(ioas)) + return PTR_ERR(ioas); + down_write(&ioas->iopt.iova_rwsem); +- rc = iopt_reserve_iova(&ioas->iopt, start, start + length - 1, NULL); ++ rc = iopt_reserve_iova(&ioas->iopt, start, last, NULL); + up_write(&ioas->iopt.iova_rwsem); + iommufd_put_object(&ioas->obj); + return rc; +-- +2.51.0 + diff --git a/queue-6.6/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch b/queue-6.6/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch new file mode 100644 index 0000000000..615c1704b5 --- /dev/null +++ b/queue-6.6/ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch @@ -0,0 +1,48 @@ +From 6ab9b46dad612ea453c7ddd972c8b437abdcae1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 13:39:03 +0300 +Subject: ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() + +From: Dmitry Skorodumov + +[ Upstream commit 0c57ff008a11f24f7f05fa760222692a00465fec ] + +Packets with pkt_type == PACKET_LOOPBACK are captured by +handle_frame() function, but they don't have L2 header. +We should not process them in handle_mode_l2(). + +This doesn't affect old L2 functionality, since handling +was anyway incorrect. + +Handle them the same way as in br_handle_frame(): +just pass the skb. + +To observe invalid behaviour, just start "ping -b" on bcast address +of port-interface. + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Signed-off-by: Dmitry Skorodumov +Link: https://patch.msgid.link/20251202103906.4087675-1-skorodumov.dmitry@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index ca62188a317ad..83bd65a227709 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -737,6 +737,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + ++ if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) ++ return RX_HANDLER_PASS; ++ + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.6/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch b/queue-6.6/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch new file mode 100644 index 0000000000..23ae68a9ca --- /dev/null +++ b/queue-6.6/ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch @@ -0,0 +1,80 @@ +From 125af2e18ffe0c55db5a3d2f8aa27b9fd8e07107 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 16:52:13 +0800 +Subject: ipvs: fix ipv4 null-ptr-deref in route error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Slavin Liu + +[ Upstream commit ad891bb3d079a46a821bf2b8867854645191bab0 ] + +The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure() +without ensuring skb->dev is set, leading to a NULL pointer dereference +in fib_compute_spec_dst() when ipv4_link_failure() attempts to send +ICMP destination unreachable messages. + +The issue emerged after commit ed0de45a1008 ("ipv4: recompile ip options +in ipv4_link_failure") started calling __ip_options_compile() from +ipv4_link_failure(). This code path eventually calls fib_compute_spec_dst() +which dereferences skb->dev. An attempt was made to fix the NULL skb->dev +dereference in commit 0113d9c9d1cc ("ipv4: fix null-deref in +ipv4_link_failure"), but it only addressed the immediate dev_net(skb->dev) +dereference by using a fallback device. The fix was incomplete because +fib_compute_spec_dst() later in the call chain still accesses skb->dev +directly, which remains NULL when IPVS calls dst_link_failure(). + +The crash occurs when: +1. IPVS processes a packet in NAT mode with a misconfigured destination +2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route +3. The error path calls dst_link_failure(skb) with skb->dev == NULL +4. ipv4_link_failure() → ipv4_send_dest_unreach() → + __ip_options_compile() → fib_compute_spec_dst() +5. fib_compute_spec_dst() dereferences NULL skb->dev + +Apply the same fix used for IPv6 in commit 326bf17ea5d4 ("ipvs: fix +ipv6 route unreach panic"): set skb->dev from skb_dst(skb)->dev before +calling dst_link_failure(). + +KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f] +CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2 +RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233 +RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285 +Call Trace: + + spec_dst_fill net/ipv4/ip_options.c:232 + spec_dst_fill net/ipv4/ip_options.c:229 + __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330 + ipv4_send_dest_unreach net/ipv4/route.c:1252 + ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265 + dst_link_failure include/net/dst.h:437 + __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412 + ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764 + +Fixes: ed0de45a1008 ("ipv4: recompile ip options in ipv4_link_failure") +Signed-off-by: Slavin Liu +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/ipvs/ip_vs_xmit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 0103c4a4d10a5..2877706f0162f 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -409,6 +409,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + return -1; + + err_unreach: ++ if (!skb->dev) ++ skb->dev = skb_dst(skb)->dev; ++ + dst_link_failure(skb); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.6/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch b/queue-6.6/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch new file mode 100644 index 0000000000..89481c551b --- /dev/null +++ b/queue-6.6/mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch @@ -0,0 +1,96 @@ +From 89b87fa07cc21adf402b76bbaf3a9c99bfc2fba4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:13 +0100 +Subject: mlxsw: spectrum_mr: Fix use-after-free when updating multicast route + stats + +From: Ido Schimmel + +[ Upstream commit 8ac1dacec458f55f871f7153242ed6ab60373b90 ] + +Cited commit added a dedicated mutex (instead of RTNL) to protect the +multicast route list, so that it will not change while the driver +periodically traverses it in order to update the kernel about multicast +route stats that were queried from the device. + +One instance of list entry deletion (during route replace) was missed +and it can result in a use-after-free [1]. + +Fix by acquiring the mutex before deleting the entry from the list and +releasing it afterwards. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] +Read of size 8 at addr ffff8881523c2fa8 by task kworker/2:5/22043 + +CPU: 2 UID: 0 PID: 22043 Comm: kworker/2:5 Not tainted 6.18.0-rc1-custom-g1a3d6d7cd014 #1 PREEMPT(full) +Hardware name: Mellanox Technologies Ltd. MSN2010/SA002610, BIOS 5.6.5 08/24/2017 +Workqueue: mlxsw_core mlxsw_sp_mr_stats_update [mlxsw_spectrum] +Call Trace: + + dump_stack_lvl+0xba/0x110 + print_report+0x174/0x4f5 + kasan_report+0xdf/0x110 + mlxsw_sp_mr_stats_update+0x4a5/0x540 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:1006 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + mlxsw_sp_mr_route_add+0xd8/0x4770 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 29933: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x43/0x70 + kfree+0x14e/0x700 + mlxsw_sp_mr_route_add+0x2dea/0x4770 drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c:444 [mlxsw_spectrum] + mlxsw_sp_router_fibmr_event_work+0x371/0xad0 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:7965 [mlxsw_spectrum] + process_one_work+0x9cc/0x18e0 + worker_thread+0x5df/0xe40 + kthread+0x3b8/0x730 + ret_from_fork+0x3e9/0x560 + ret_from_fork_asm+0x1a/0x30 + +Fixes: f38656d06725 ("mlxsw: spectrum_mr: Protect multicast route list with a lock") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/f996feecfd59fde297964bfc85040b6d83ec6089.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +index 5afe6b155ef0d..81935f87bfcd7 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table, + rhashtable_remove_fast(&mr_table->route_ht, + &mr_orig_route->ht_node, + mlxsw_sp_mr_route_ht_params); ++ mutex_lock(&mr_table->route_list_lock); + list_del(&mr_orig_route->node); ++ mutex_unlock(&mr_table->route_list_lock); + mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); + } + +-- +2.51.0 + diff --git a/queue-6.6/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch b/queue-6.6/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch new file mode 100644 index 0000000000..9d96904251 --- /dev/null +++ b/queue-6.6/mlxsw-spectrum_router-fix-neighbour-use-after-free.patch @@ -0,0 +1,199 @@ +From 630cc1d6e6a73c73fb7edfb6f03511a5e801c19a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:12 +0100 +Subject: mlxsw: spectrum_router: Fix neighbour use-after-free + +From: Ido Schimmel + +[ Upstream commit 8b0e69763ef948fb872a7767df4be665d18f5fd4 ] + +We sometimes observe use-after-free when dereferencing a neighbour [1]. +The problem seems to be that the driver stores a pointer to the +neighbour, but without holding a reference on it. A reference is only +taken when the neighbour is used by a nexthop. + +Fix by simplifying the reference counting scheme. Always take a +reference when storing a neighbour pointer in a neighbour entry. Avoid +taking a referencing when the neighbour is used by a nexthop as the +neighbour entry associated with the nexthop already holds a reference. + +Tested by running the test that uncovered the problem over 300 times. +Without this patch the problem was reproduced after a handful of +iterations. + +[1] +BUG: KASAN: slab-use-after-free in mlxsw_sp_neigh_entry_update+0x2d4/0x310 +Read of size 8 at addr ffff88817f8e3420 by task ip/3929 + +CPU: 3 UID: 0 PID: 3929 Comm: ip Not tainted 6.18.0-rc4-virtme-g36b21a067510 #3 PREEMPT(full) +Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 +Call Trace: + + dump_stack_lvl+0x6f/0xa0 + print_address_description.constprop.0+0x6e/0x300 + print_report+0xfc/0x1fb + kasan_report+0xe4/0x110 + mlxsw_sp_neigh_entry_update+0x2d4/0x310 + mlxsw_sp_router_rif_gone_sync+0x35f/0x510 + mlxsw_sp_rif_destroy+0x1ea/0x730 + mlxsw_sp_inetaddr_port_vlan_event+0xa1/0x1b0 + __mlxsw_sp_inetaddr_lag_event+0xcc/0x130 + __mlxsw_sp_inetaddr_event+0xf5/0x3c0 + mlxsw_sp_router_netdevice_event+0x1015/0x1580 + notifier_call_chain+0xcc/0x150 + call_netdevice_notifiers_info+0x7e/0x100 + __netdev_upper_dev_unlink+0x10b/0x210 + netdev_upper_dev_unlink+0x79/0xa0 + vrf_del_slave+0x18/0x50 + do_set_master+0x146/0x7d0 + do_setlink.isra.0+0x9a0/0x2880 + rtnl_newlink+0x637/0xb20 + rtnetlink_rcv_msg+0x6fe/0xb90 + netlink_rcv_skb+0x123/0x380 + netlink_unicast+0x4a3/0x770 + netlink_sendmsg+0x75b/0xc90 + __sock_sendmsg+0xbe/0x160 + ____sys_sendmsg+0x5b2/0x7d0 + ___sys_sendmsg+0xfd/0x180 + __sys_sendmsg+0x124/0x1c0 + do_syscall_64+0xbb/0xfd0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[...] + +Allocated by task 109: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7b/0x90 + __kmalloc_noprof+0x2c1/0x790 + neigh_alloc+0x6af/0x8f0 + ___neigh_create+0x63/0xe90 + mlxsw_sp_nexthop_neigh_init+0x430/0x7e0 + mlxsw_sp_nexthop_type_init+0x212/0x960 + mlxsw_sp_nexthop6_group_info_init.constprop.0+0x81f/0x1280 + mlxsw_sp_nexthop6_group_get+0x392/0x6a0 + mlxsw_sp_fib6_entry_create+0x46a/0xfd0 + mlxsw_sp_router_fib6_replace+0x1ed/0x5f0 + mlxsw_sp_router_fib6_event_work+0x10a/0x2a0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Freed by task 154: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kmem_cache_free_bulk.part.0+0x1eb/0x5e0 + kvfree_rcu_bulk+0x1f2/0x260 + kfree_rcu_work+0x130/0x1b0 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Last potentially related work creation: + kasan_save_stack+0x30/0x50 + kasan_record_aux_stack+0x8c/0xa0 + kvfree_call_rcu+0x93/0x5b0 + mlxsw_sp_router_neigh_event_work+0x67d/0x860 + process_one_work+0xd57/0x1390 + worker_thread+0x4d6/0xd40 + kthread+0x355/0x5b0 + ret_from_fork+0x1d4/0x270 + ret_from_fork_asm+0x11/0x20 + +Fixes: 6cf3c971dc84 ("mlxsw: spectrum_router: Add private neigh table") +Signed-off-by: Ido Schimmel +Reviewed-by: Petr Machata +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/92d75e21d95d163a41b5cea67a15cd33f547cba6.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlxsw/spectrum_router.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index f5c34218ba85b..4cd79473ace54 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2264,6 +2264,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + if (!neigh_entry) + return NULL; + ++ neigh_hold(n); + neigh_entry->key.n = n; + neigh_entry->rif = rif; + INIT_LIST_HEAD(&neigh_entry->nexthop_list); +@@ -2273,6 +2274,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, + + static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) + { ++ neigh_release(neigh_entry->key.n); + kfree(neigh_entry); + } + +@@ -4203,6 +4205,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + if (err) + goto err_neigh_entry_insert; + ++ neigh_release(old_n); ++ + read_lock_bh(&n->lock); + nud_state = n->nud_state; + dead = n->dead; +@@ -4211,14 +4215,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, + + list_for_each_entry(nh, &neigh_entry->nexthop_list, + neigh_list_node) { +- neigh_release(old_n); +- neigh_clone(n); + __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + } + +- neigh_release(n); +- + return 0; + + err_neigh_entry_insert: +@@ -4311,6 +4311,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, + } + } + ++ /* Release the reference taken by neigh_lookup() / neigh_create() since ++ * neigh_entry already holds one. ++ */ ++ neigh_release(n); ++ + /* If that is the first nexthop connected to that neigh, add to + * nexthop_neighs_list + */ +@@ -4337,11 +4342,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) + { + struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; +- struct neighbour *n; + + if (!neigh_entry) + return; +- n = neigh_entry->key.n; + + __mlxsw_sp_nexthop_neigh_update(nh, true); + list_del(&nh->neigh_list_node); +@@ -4355,8 +4358,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, + + if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) + mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); +- +- neigh_release(n); + } + + static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) +-- +2.51.0 + diff --git a/queue-6.6/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch b/queue-6.6/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch new file mode 100644 index 0000000000..ddf68ce591 --- /dev/null +++ b/queue-6.6/mlxsw-spectrum_router-fix-possible-neighbour-referen.patch @@ -0,0 +1,64 @@ +From 434e03e1048d44e1c203b12cb5b905e1e1213aa3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Dec 2025 18:44:11 +0100 +Subject: mlxsw: spectrum_router: Fix possible neighbour reference count leak + +From: Ido Schimmel + +[ Upstream commit b6b638bda240395dff49a87403b2e32493e56d2a ] + +mlxsw_sp_router_schedule_work() takes a reference on a neighbour, +expecting a work item to release it later on. However, we might fail to +schedule the work item, in which case the neighbour reference count will +be leaked. + +Fix by taking the reference just before scheduling the work item. Note +that mlxsw_sp_router_schedule_work() can receive a NULL neighbour +pointer, but neigh_clone() handles that correctly. + +Spotted during code review, did not actually observe the reference count +leak. + +Fixes: 151b89f6025a ("mlxsw: spectrum_router: Reuse work neighbor initialization in work scheduler") +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Signed-off-by: Petr Machata +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/ec2934ae4aca187a8d8c9329a08ce93cca411378.1764695650.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index 0534b10e29c5c..f5c34218ba85b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -2857,6 +2857,11 @@ static int mlxsw_sp_router_schedule_work(struct net *net, + if (!net_work) + return NOTIFY_BAD; + ++ /* Take a reference to ensure the neighbour won't be destructed until ++ * we drop the reference in the work item. ++ */ ++ neigh_clone(n); ++ + INIT_WORK(&net_work->work, cb); + net_work->mlxsw_sp = router->mlxsw_sp; + net_work->n = n; +@@ -2880,11 +2885,6 @@ static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router, + struct net *net; + + net = neigh_parms_net(n->parms); +- +- /* Take a reference to ensure the neighbour won't be destructed until we +- * drop the reference in delayed work. +- */ +- neigh_clone(n); + return mlxsw_sp_router_schedule_work(net, router, n, + mlxsw_sp_router_neigh_event_work); + } +-- +2.51.0 + diff --git a/queue-6.6/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch b/queue-6.6/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch new file mode 100644 index 0000000000..cf05cbc143 --- /dev/null +++ b/queue-6.6/net-enetc-do-not-transmit-redirected-xdp-frames-when.patch @@ -0,0 +1,66 @@ +From 246aa74c78963064d0249bb9fbe7ad9d65a95648 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:09:19 +0800 +Subject: net: enetc: do not transmit redirected XDP frames when the link is + down + +From: Wei Fang + +[ Upstream commit 2939203ffee818f1e5ebd60bbb85a174d63aab9c ] + +In the current implementation, the enetc_xdp_xmit() always transmits +redirected XDP frames even if the link is down, but the frames cannot +be transmitted from TX BD rings when the link is down, so the frames +are still kept in the TX BD rings. If the XDP program is uninstalled, +users will see the following warning logs. + +fsl_enetc 0000:00:00.0 eno0: timeout for tx ring #6 clear + +More worse, the TX BD ring cannot work properly anymore, because the +HW PIR and CIR are not equal after the re-initialization of the TX +BD ring. At this point, the BDs between CIR and PIR are invalid, +which will cause a hardware malfunction. + +Another reason is that there is internal context in the ring prefetch +logic that will retain the state from the first incarnation of the ring +and continue prefetching from the stale location when we re-initialize +the ring. The internal context is only reset by an FLR. That is to say, +for LS1028A ENETC, software cannot set the HW CIR and PIR when +initializing the TX BD ring. + +It does not make sense to transmit redirected XDP frames when the link is +down. Add a link status check to prevent transmission in this condition. +This fixes part of the issue, but more complex cases remain. For example, +the TX BD ring may still contain unsent frames when the link goes down. +Those situations require additional patches, which will build on this +one. + +Fixes: 9d2b68cc108d ("net: enetc: add support for XDP_REDIRECT") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Reviewed-by: Hariprasad Kelam +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20251211020919.121113-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 7accf3a3e9f0d..e3ab6f4f8dbba 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1429,7 +1429,8 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames, + int xdp_tx_bd_cnt, i, k; + int xdp_tx_frm_cnt = 0; + +- if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags))) ++ if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags) || ++ !netif_carrier_ok(ndev))) + return -ENETDOWN; + + enetc_lock_mdio(); +-- +2.51.0 + diff --git a/queue-6.6/net-fec-err007885-workaround-for-xdp-tx-path.patch b/queue-6.6/net-fec-err007885-workaround-for-xdp-tx-path.patch new file mode 100644 index 0000000000..d43eb86596 --- /dev/null +++ b/queue-6.6/net-fec-err007885-workaround-for-xdp-tx-path.patch @@ -0,0 +1,49 @@ +From 10b9633f939f42eda96a92297694f876b776e41b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:59:15 +0800 +Subject: net: fec: ERR007885 Workaround for XDP TX path + +From: Wei Fang + +[ Upstream commit e8e032cd24dda7cceaa27bc2eb627f82843f0466 ] + +The ERR007885 will lead to a TDAR race condition for mutliQ when the +driver sets TDAR and the UDMA clears TDAR simultaneously or in a small +window (2-4 cycles). And it will cause the udma_tx and udma_tx_arbiter +state machines to hang. Therefore, the commit 53bb20d1faba ("net: fec: +add variable reg_desc_active to speed things up") and the commit +a179aad12bad ("net: fec: ERR007885 Workaround for conventional TX") have +added the workaround to fix the potential issue for the conventional TX +path. Similarly, the XDP TX path should also have the potential hang +issue, so add the workaround for XDP TX path. + +Fixes: 6d6b39f180b8 ("net: fec: add initial XDP support") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251128025915.2486943-1-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index ee0306ab97714..7efe4e81cf320 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -3935,7 +3935,12 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, + txq->bd.cur = bdp; + + /* Trigger transmission start */ +- writel(0, txq->bd.reg_desc_active); ++ if (!(fep->quirks & FEC_QUIRK_ERR007885) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active)) ++ writel(0, txq->bd.reg_desc_active); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.6/net-handshake-duplicate-handshake-cancellations-leak.patch b/queue-6.6/net-handshake-duplicate-handshake-cancellations-leak.patch new file mode 100644 index 0000000000..4decc819f7 --- /dev/null +++ b/queue-6.6/net-handshake-duplicate-handshake-cancellations-leak.patch @@ -0,0 +1,61 @@ +From c97d79af26547edffbba0ae17d2b1195e37a4ffd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:30:15 -0500 +Subject: net/handshake: duplicate handshake cancellations leak socket + +From: Scott Mayhew + +[ Upstream commit 15564bd67e2975002f2a8e9defee33e321d3183f ] + +When a handshake request is cancelled it is removed from the +handshake_net->hn_requests list, but it is still present in the +handshake_rhashtbl until it is destroyed. + +If a second cancellation request arrives for the same handshake request, +then remove_pending() will return false... and assuming +HANDSHAKE_F_REQ_COMPLETED isn't set in req->hr_flags, we'll continue +processing through the out_true label, where we put another reference on +the sock and a refcount underflow occurs. + +This can happen for example if a handshake times out - particularly if +the SUNRPC client sends the AUTH_TLS probe to the server but doesn't +follow it up with the ClientHello due to a problem with tlshd. When the +timeout is hit on the server, the server will send a FIN, which triggers +a cancellation request via xs_reset_transport(). When the timeout is +hit on the client, another cancellation request happens via +xs_tls_handshake_sync(). + +Add a test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED) in the pending cancel +path so duplicate cancels can be detected. + +Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests") +Suggested-by: Chuck Lever +Signed-off-by: Scott Mayhew +Reviewed-by: Chuck Lever +Link: https://patch.msgid.link/20251209193015.3032058-1-smayhew@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/handshake/request.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/handshake/request.c b/net/handshake/request.c +index 94d5cef3e048b..0ac126b0add60 100644 +--- a/net/handshake/request.c ++++ b/net/handshake/request.c +@@ -325,7 +325,11 @@ bool handshake_req_cancel(struct sock *sk) + + hn = handshake_pernet(net); + if (hn && remove_pending(hn, req)) { +- /* Request hadn't been accepted */ ++ /* Request hadn't been accepted - mark cancelled */ ++ if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { ++ trace_handshake_cancel_busy(net, req, sk); ++ return false; ++ } + goto out_true; + } + if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { +-- +2.51.0 + diff --git a/queue-6.6/net-hns3-add-vlan-id-validation-before-using.patch b/queue-6.6/net-hns3-add-vlan-id-validation-before-using.patch new file mode 100644 index 0000000000..0fc7043856 --- /dev/null +++ b/queue-6.6/net-hns3-add-vlan-id-validation-before-using.patch @@ -0,0 +1,46 @@ +From 8a145435480c6524ab63f2aaca40e53766de08de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:37 +0800 +Subject: net: hns3: add VLAN id validation before using + +From: Jian Shen + +[ Upstream commit 6ef935e65902bfed53980ad2754b06a284ea8ac1 ] + +Currently, the VLAN id may be used without validation when +receive a VLAN configuration mailbox from VF. The length of +vlan_del_fail_bmap is BITS_TO_LONGS(VLAN_N_VID). It may cause +out-of-bounds memory access once the VLAN id is bigger than +or equal to VLAN_N_VID. + +Therefore, VLAN id needs to be checked to ensure it is within +the range of VLAN_N_VID. + +Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-4-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 2fa64099e8be2..2df0c6305b908 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -10479,6 +10479,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, + bool writen_to_tbl = false; + int ret = 0; + ++ if (vlan_id >= VLAN_N_VID) ++ return -EINVAL; ++ + /* When device is resetting or reset failed, firmware is unable to + * handle mailbox. Just record the vlan id, and remove it after + * reset finished. +-- +2.51.0 + diff --git a/queue-6.6/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch b/queue-6.6/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch new file mode 100644 index 0000000000..7b26415b99 --- /dev/null +++ b/queue-6.6/net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch @@ -0,0 +1,52 @@ +From f19b0d8ab7bd92fc34dc9a7fe85798bdba6d8bfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:35 +0800 +Subject: net: hns3: using the num_tqps in the vf driver to apply for resources + +From: Jian Shen + +[ Upstream commit c2a16269742e176fccdd0ef9c016a233491a49ad ] + +Currently, hdev->htqp is allocated using hdev->num_tqps, and kinfo->tqp +is allocated using kinfo->num_tqps. However, kinfo->num_tqps is set to +min(new_tqps, hdev->num_tqps); Therefore, kinfo->num_tqps may be smaller +than hdev->num_tqps, which causes some hdev->htqp[i] to remain +uninitialized in hclgevf_knic_setup(). + +Thus, this patch allocates hdev->htqp and kinfo->tqp using hdev->num_tqps, +ensuring that the lengths of hdev->htqp and kinfo->tqp are consistent +and that all elements are properly initialized. + +Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-2-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 68a9aeeed3da0..c7e5b83ac4a84 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -333,12 +333,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) + new_tqps = kinfo->rss_size * num_tc; + kinfo->num_tqps = min(new_tqps, hdev->num_tqps); + +- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, ++ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, + sizeof(struct hnae3_queue *), GFP_KERNEL); + if (!kinfo->tqp) + return -ENOMEM; + +- for (i = 0; i < kinfo->num_tqps; i++) { ++ for (i = 0; i < hdev->num_tqps; i++) { + hdev->htqp[i].q.handle = &hdev->nic; + hdev->htqp[i].q.tqp_index = i; + kinfo->tqp[i] = &hdev->htqp[i].q; +-- +2.51.0 + diff --git a/queue-6.6/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch b/queue-6.6/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch new file mode 100644 index 0000000000..8c882ec1aa --- /dev/null +++ b/queue-6.6/net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch @@ -0,0 +1,49 @@ +From fa4fe5c3b21f61994135da81ab39a0a56c5ddc3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Dec 2025 10:37:36 +0800 +Subject: net: hns3: using the num_tqps to check whether tqp_index is out of + range when vf get ring info from mbx + +From: Jian Shen + +[ Upstream commit d180c11aa8a6fa735f9ac2c72c61364a9afc2ba7 ] + +Currently, rss_size = num_tqps / tc_num. If tc_num is 1, then num_tqps +equals rss_size. However, if the tc_num is greater than 1, then rss_size +will be less than num_tqps, causing the tqp_index check for subsequent TCs +using rss_size to always fail. + +This patch uses the num_tqps to check whether tqp_index is out of range, +instead of rss_size. + +Fixes: 326334aad024 ("net: hns3: add a check for tqp_index in hclge_get_ring_chain_from_mbx()") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251211023737.2327018-3-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index 61e155c4d441e..a961e90a85a67 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx( + return -EINVAL; + + for (i = 0; i < ring_num; i++) { +- if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { ++ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { + dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", + req->msg.param[i].tqp_index, +- vport->nic.kinfo.rss_size - 1U); ++ vport->nic.kinfo.num_tqps - 1U); + return -EINVAL; + } + } +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch b/queue-6.6/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch new file mode 100644 index 0000000000..b82e093b56 --- /dev/null +++ b/queue-6.6/net-mlx5-drain-firmware-reset-in-shutdown-callback.patch @@ -0,0 +1,38 @@ +From 0eff167db5fd2ac3aaf627f0b6d9b269e79258e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:10 +0200 +Subject: net/mlx5: Drain firmware reset in shutdown callback + +From: Moshe Shemesh + +[ Upstream commit 5846a365fc6476b02d6766963cf0985520f0385f ] + +Invoke drain_fw_reset() in the shutdown callback to ensure all +firmware reset handling is completed before shutdown proceeds. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 8a11e410f7c13..df6eeb0f57bcd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -2164,6 +2164,7 @@ static void shutdown(struct pci_dev *pdev) + + mlx5_core_info(dev, "Shutdown was called\n"); + set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); ++ mlx5_drain_fw_reset(dev); + mlx5_drain_health_wq(dev); + err = mlx5_try_fast_unload(dev); + if (err) +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch b/queue-6.6/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch new file mode 100644 index 0000000000..9b1196a937 --- /dev/null +++ b/queue-6.6/net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch @@ -0,0 +1,45 @@ +From bcb2ab40259b77d3ec5394c9918ae32223ac6269 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:09 +0200 +Subject: net/mlx5: fw reset, clear reset requested on drain_fw_reset + +From: Moshe Shemesh + +[ Upstream commit 89a898d63f6f588acf5c104c65c94a38b68c69a6 ] + +drain_fw_reset() waits for ongoing firmware reset events and blocks new +event handling, but does not clear the reset requested flag, and may +keep sync reset polling. + +To fix it, call mlx5_sync_reset_clear_reset_requested() to clear the +flag, stop sync reset polling, and resume health polling, ensuring +health issues are still detected after the firmware reset drain. + +Fixes: 16d42d313350 ("net/mlx5: Drain fw_reset when removing device") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 4d64d179b5dd7..dc7afc9e7777d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -804,7 +804,8 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev) + cancel_work_sync(&fw_reset->reset_reload_work); + cancel_work_sync(&fw_reset->reset_now_work); + cancel_work_sync(&fw_reset->reset_abort_work); +- cancel_delayed_work(&fw_reset->reset_timeout_work); ++ if (test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) ++ mlx5_sync_reset_clear_reset_requested(dev, true); + } + + static const struct devlink_param mlx5_fw_reset_devlink_params[] = { +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch b/queue-6.6/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch new file mode 100644 index 0000000000..9974f28365 --- /dev/null +++ b/queue-6.6/net-mlx5-fw_tracer-handle-escaped-percent-properly.patch @@ -0,0 +1,84 @@ +From dd8866b9504bb82018195e19707623cb8a430de5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:12 +0200 +Subject: net/mlx5: fw_tracer, Handle escaped percent properly + +From: Shay Drory + +[ Upstream commit c0289f67f7d6a0dfba0e92cfe661a5c70c8c6e92 ] + +The firmware tracer's format string validation and parameter counting +did not properly handle escaped percent signs (%%). This caused +fw_tracer to count more parameters when trace format strings contained +literal percent characters. + +To fix it, allow %% to pass string validation and skip %% sequences when +counting parameters since they represent literal percent signs rather +than format specifiers. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reported-by: Breno Leitao +Reviewed-by: Moshe Shemesh +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 197c306d350bf..0a33ab5f53fd3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -368,11 +368,11 @@ static bool mlx5_is_valid_spec(const char *str) + while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') + str++; + +- /* Check if it's a valid integer/hex specifier: ++ /* Check if it's a valid integer/hex specifier or %%: + * Valid formats: %x, %d, %i, %u, etc. + */ + if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && +- *str != 'u' && *str != 'c') ++ *str != 'u' && *str != 'c' && *str != '%') + return false; + + return true; +@@ -390,7 +390,11 @@ static bool mlx5_tracer_validate_params(const char *str) + if (!mlx5_is_valid_spec(substr + 1)) + return false; + +- substr = strstr(substr + 1, PARAM_CHAR); ++ if (*(substr + 1) == '%') ++ substr = strstr(substr + 2, PARAM_CHAR); ++ else ++ substr = strstr(substr + 1, PARAM_CHAR); ++ + } + + return true; +@@ -469,11 +473,15 @@ static int mlx5_tracer_get_num_of_params(char *str) + substr = strstr(pstr, VAL_PARM); + } + +- /* count all the % characters */ ++ /* count all the % characters, but skip %% (escaped percent) */ + substr = strstr(str, PARAM_CHAR); + while (substr) { +- num_of_params += 1; +- str = substr + 1; ++ if (*(substr + 1) != '%') { ++ num_of_params += 1; ++ str = substr + 1; ++ } else { ++ str = substr + 2; ++ } + substr = strstr(str, PARAM_CHAR); + } + +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5-fw_tracer-validate-format-string-parameters.patch b/queue-6.6/net-mlx5-fw_tracer-validate-format-string-parameters.patch new file mode 100644 index 0000000000..4b80912228 --- /dev/null +++ b/queue-6.6/net-mlx5-fw_tracer-validate-format-string-parameters.patch @@ -0,0 +1,195 @@ +From aa54a5302b85b67ba0a7a54dd1906ff8e719f2c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:11 +0200 +Subject: net/mlx5: fw_tracer, Validate format string parameters + +From: Shay Drory + +[ Upstream commit b35966042d20b14e2d83330049f77deec5229749 ] + +Add validation for format string parameters in the firmware tracer to +prevent potential security vulnerabilities and crashes from malformed +format strings received from firmware. + +The firmware tracer receives format strings from the device firmware and +uses them to format trace messages. Without proper validation, bad +firmware could provide format strings with invalid format specifiers +(e.g., %s, %p, %n) that could lead to crashes, or other undefined +behavior. + +Add mlx5_tracer_validate_params() to validate that all format specifiers +in trace strings are limited to safe integer/hex formats (%x, %d, %i, +%u, %llx, %lx, etc.). Reject strings containing other format types that +could be used to access arbitrary memory or cause crashes. +Invalid format strings are added to the trace output for visibility with +"BAD_FORMAT: " prefix. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Shay Drory +Reviewed-by: Moshe Shemesh +Reported-by: Breno Leitao +Closes: https://lore.kernel.org/netdev/hanz6rzrb2bqbplryjrakvkbmv4y5jlmtthnvi3thg5slqvelp@t3s3erottr6s/ +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/diag/fw_tracer.c | 83 ++++++++++++++++--- + .../mellanox/mlx5/core/diag/fw_tracer.h | 1 + + 2 files changed, 74 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index 85d3bfa0780c6..197c306d350bf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -33,6 +33,7 @@ + #include "lib/eq.h" + #include "fw_tracer.h" + #include "fw_tracer_tracepoint.h" ++#include + + static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) + { +@@ -358,6 +359,43 @@ static const char *VAL_PARM = "%llx"; + static const char *REPLACE_64_VAL_PARM = "%x%x"; + static const char *PARAM_CHAR = "%"; + ++static bool mlx5_is_valid_spec(const char *str) ++{ ++ /* Parse format specifiers to find the actual type. ++ * Structure: %[flags][width][.precision][length]type ++ * Skip flags, width, precision & length. ++ */ ++ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l') ++ str++; ++ ++ /* Check if it's a valid integer/hex specifier: ++ * Valid formats: %x, %d, %i, %u, etc. ++ */ ++ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' && ++ *str != 'u' && *str != 'c') ++ return false; ++ ++ return true; ++} ++ ++static bool mlx5_tracer_validate_params(const char *str) ++{ ++ const char *substr = str; ++ ++ if (!str) ++ return false; ++ ++ substr = strstr(substr, PARAM_CHAR); ++ while (substr) { ++ if (!mlx5_is_valid_spec(substr + 1)) ++ return false; ++ ++ substr = strstr(substr + 1, PARAM_CHAR); ++ } ++ ++ return true; ++} ++ + static int mlx5_tracer_message_hash(u32 message_id) + { + return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); +@@ -419,6 +457,10 @@ static int mlx5_tracer_get_num_of_params(char *str) + char *substr, *pstr = str; + int num_of_params = 0; + ++ /* Validate that all parameters are valid before processing */ ++ if (!mlx5_tracer_validate_params(str)) ++ return -EINVAL; ++ + /* replace %llx with %x%x */ + substr = strstr(pstr, VAL_PARM); + while (substr) { +@@ -570,14 +612,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, + { + char tmp[512]; + +- snprintf(tmp, sizeof(tmp), str_frmt->string, +- str_frmt->params[0], +- str_frmt->params[1], +- str_frmt->params[2], +- str_frmt->params[3], +- str_frmt->params[4], +- str_frmt->params[5], +- str_frmt->params[6]); ++ if (str_frmt->invalid_string) ++ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string); ++ else ++ snprintf(tmp, sizeof(tmp), str_frmt->string, ++ str_frmt->params[0], ++ str_frmt->params[1], ++ str_frmt->params[2], ++ str_frmt->params[3], ++ str_frmt->params[4], ++ str_frmt->params[5], ++ str_frmt->params[6]); + + trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, + str_frmt->event_id, tmp); +@@ -609,6 +654,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer, + return 0; + } + ++static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer, ++ struct tracer_string_format *cur_string) ++{ ++ cur_string->invalid_string = true; ++ list_add_tail(&cur_string->list, &tracer->ready_strings_list); ++} ++ + static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + struct tracer_event *tracer_event) + { +@@ -619,12 +671,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + if (!cur_string) + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + +- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); +- cur_string->last_param_num = 0; + cur_string->event_id = tracer_event->event_id; + cur_string->tmsn = tracer_event->string_event.tmsn; + cur_string->timestamp = tracer_event->string_event.timestamp; + cur_string->lost = tracer_event->lost_event; ++ cur_string->last_param_num = 0; ++ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string); ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s Invalid format string parameters\n", ++ __func__); ++ mlx5_tracer_handle_bad_format_string(tracer, cur_string); ++ return 0; ++ } + if (cur_string->num_of_params == 0) /* trace with no params */ + list_add_tail(&cur_string->list, &tracer->ready_strings_list); + } else { +@@ -634,6 +692,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, + __func__, tracer_event->string_event.tmsn); + return mlx5_tracer_handle_raw_string(tracer, tracer_event); + } ++ if (cur_string->num_of_params < 0) { ++ pr_debug("%s string parameter of invalid string, dumping\n", ++ __func__); ++ return 0; ++ } + cur_string->last_param_num += 1; + if (cur_string->last_param_num > TRACER_MAX_PARAMS) { + pr_debug("%s Number of params exceeds the max (%d)\n", +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +index 5c548bb74f07b..30d0bcba88479 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h +@@ -125,6 +125,7 @@ struct tracer_string_format { + struct list_head list; + u32 timestamp; + bool lost; ++ bool invalid_string; + }; + + enum mlx5_fw_tracer_ownership_state { +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5-serialize-firmware-reset-with-devlink.patch b/queue-6.6/net-mlx5-serialize-firmware-reset-with-devlink.patch new file mode 100644 index 0000000000..8836928810 --- /dev/null +++ b/queue-6.6/net-mlx5-serialize-firmware-reset-with-devlink.patch @@ -0,0 +1,209 @@ +From d10eb48c91b28a5a6779da747df3e7fa7fd3e46d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 14:56:13 +0200 +Subject: net/mlx5: Serialize firmware reset with devlink + +From: Shay Drory + +[ Upstream commit 367e501f8b095eca08d2eb0ba4ccea5b5e82c169 ] + +The firmware reset mechanism can be triggered by asynchronous events, +which may race with other devlink operations like devlink reload or +devlink dev eswitch set, potentially leading to inconsistent states. + +This patch addresses the race by using the devl_lock to serialize the +firmware reset against other devlink operations. When a reset is +requested, the driver attempts to acquire the lock. If successful, it +sets a flag to block devlink reload or eswitch changes, ACKs the reset +to firmware and then releases the lock. If the lock is already held by +another operation, the driver NACKs the firmware reset request, +indicating that the reset cannot proceed. + +Firmware reset does not keep the devl_lock and instead uses an internal +firmware reset bit. This is because firmware resets can be triggered by +asynchronous events, and processed in different threads. It is illegal +and unsafe to acquire a lock in one thread and attempt to release it in +another, as lock ownership is intrinsically thread-specific. + +This change ensures that firmware resets and other devlink operations +are mutually exclusive during the critical reset request phase, +preventing race conditions. + +Fixes: 38b9f903f22b ("net/mlx5: Handle sync reset request event") +Signed-off-by: Shay Drory +Reviewed-by: Mateusz Berezecki +Reviewed-by: Moshe Shemesh +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1765284977-1363052-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/devlink.c | 5 +++ + .../mellanox/mlx5/core/eswitch_offloads.c | 6 +++ + .../ethernet/mellanox/mlx5/core/fw_reset.c | 45 +++++++++++++++++-- + .../ethernet/mellanox/mlx5/core/fw_reset.h | 1 + + 4 files changed, 53 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 8489b5087d9c6..b2532b1c9565a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -144,6 +144,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, + bool sf_dev_allocated; + int ret = 0; + ++ if (mlx5_fw_reset_in_progress(dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Can't reload during firmware reset"); ++ return -EBUSY; ++ } ++ + if (mlx5_dev_is_lightweight(dev)) { + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 86fb8197594f5..c218593dc40f4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -51,6 +51,7 @@ + #include "devlink.h" + #include "lag/lag.h" + #include "en/tc/post_meter.h" ++#include "fw_reset.h" + + /* There are two match-all miss flows, one for unicast dst mac and + * one for multicast. +@@ -3716,6 +3717,11 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, + if (IS_ERR(esw)) + return PTR_ERR(esw); + ++ if (mlx5_fw_reset_in_progress(esw->dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Can't change eswitch mode during firmware reset"); ++ return -EBUSY; ++ } ++ + if (esw_mode_from_devlink(mode, &mlx5_mode)) + return -EINVAL; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index bdcd9e5306331..f7e139279f5f8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -15,6 +15,7 @@ enum { + MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, + MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, + MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, ++ MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, + }; + + struct mlx5_fw_reset { +@@ -125,6 +126,16 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty + return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL); + } + ++bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev) ++{ ++ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; ++ ++ if (!fw_reset) ++ return false; ++ ++ return test_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); ++} ++ + static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev, + u8 *reset_method) + { +@@ -240,6 +251,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); + devl_unlock(devlink); + } ++ ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + } + + static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) +@@ -431,27 +444,48 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, + reset_request_work); + struct mlx5_core_dev *dev = fw_reset->dev; ++ bool nack_request = false; ++ struct devlink *devlink; + int err; + + err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method); +- if (err) ++ if (err) { ++ nack_request = true; + mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err); ++ } else if (!mlx5_is_reset_now_capable(dev, fw_reset->reset_method) || ++ test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, ++ &fw_reset->reset_flags)) { ++ nack_request = true; ++ } + +- if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || +- !mlx5_is_reset_now_capable(dev, fw_reset->reset_method)) { ++ devlink = priv_to_devlink(dev); ++ /* For external resets, try to acquire devl_lock. Skip if devlink reset is ++ * pending (lock already held) ++ */ ++ if (nack_request || ++ (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, ++ &fw_reset->reset_flags) && ++ !devl_trylock(devlink))) { + err = mlx5_fw_reset_set_reset_sync_nack(dev); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", + err ? "Failed" : "Sent"); + return; + } ++ + if (mlx5_sync_reset_set_reset_requested(dev)) +- return; ++ goto unlock; ++ ++ set_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + + err = mlx5_fw_reset_set_reset_sync_ack(dev); + if (err) + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err); + else + mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n"); ++ ++unlock: ++ if (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) ++ devl_unlock(devlink); + } + + static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id) +@@ -685,6 +719,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work) + + if (mlx5_sync_reset_clear_reset_requested(dev, true)) + return; ++ ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); + } + +@@ -721,6 +757,7 @@ static void mlx5_sync_reset_timeout_work(struct work_struct *work) + + if (mlx5_sync_reset_clear_reset_requested(dev, true)) + return; ++ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Timeout.\n"); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +index d5b28525c960d..2d96b2adc1cdf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +@@ -10,6 +10,7 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty + int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, + struct netlink_ext_ack *extack); + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); ++bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev); + + int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); + void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5-skip-hotplug-check-on-sync-reset-using-hot-.patch b/queue-6.6/net-mlx5-skip-hotplug-check-on-sync-reset-using-hot-.patch new file mode 100644 index 0000000000..8da02b38eb --- /dev/null +++ b/queue-6.6/net-mlx5-skip-hotplug-check-on-sync-reset-using-hot-.patch @@ -0,0 +1,66 @@ +From 42f3b9e01942489cc0ef6e55403aaaf1c225a77d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Sep 2024 13:17:53 -0700 +Subject: net/mlx5: Skip HotPlug check on sync reset using hot reset + +From: Moshe Shemesh + +[ Upstream commit 48bb52b0bc6693afb17a6024bab925b25fec44a1 ] + +Sync reset request is nacked by the driver when PCIe bridge connected to +mlx5 device has HotPlug interrupt enabled. However, when using reset +method of hot reset this check can be skipped as Hotplug is supported on +this reset method. + +Signed-off-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20240911201757.1505453-12-saeed@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 367e501f8b09 ("net/mlx5: Serialize firmware reset with devlink") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index dc7afc9e7777d..bdcd9e5306331 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -396,7 +396,8 @@ static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id) + return 0; + } + +-static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev) ++static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev, ++ u8 reset_method) + { + u16 dev_id; + int err; +@@ -412,9 +413,11 @@ static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev) + } + + #if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE) +- err = mlx5_check_hotplug_interrupt(dev); +- if (err) +- return false; ++ if (reset_method != MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET) { ++ err = mlx5_check_hotplug_interrupt(dev); ++ if (err) ++ return false; ++ } + #endif + + err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id); +@@ -435,7 +438,7 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) + mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err); + + if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || +- !mlx5_is_reset_now_capable(dev)) { ++ !mlx5_is_reset_now_capable(dev, fw_reset->reset_method)) { + err = mlx5_fw_reset_set_reset_sync_nack(dev); + mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", + err ? "Failed" : "Sent"); +-- +2.51.0 + diff --git a/queue-6.6/net-openvswitch-fix-middle-attribute-validation-in-p.patch b/queue-6.6/net-openvswitch-fix-middle-attribute-validation-in-p.patch new file mode 100644 index 0000000000..e34527401b --- /dev/null +++ b/queue-6.6/net-openvswitch-fix-middle-attribute-validation-in-p.patch @@ -0,0 +1,112 @@ +From c9981f012de41c84613e083f1b75433cecf005b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Dec 2025 11:53:32 +0100 +Subject: net: openvswitch: fix middle attribute validation in push_nsh() + action + +From: Ilya Maximets + +[ Upstream commit 5ace7ef87f059d68b5f50837ef3e8a1a4870c36e ] + +The push_nsh() action structure looks like this: + + OVS_ACTION_ATTR_PUSH_NSH(OVS_KEY_ATTR_NSH(OVS_NSH_KEY_ATTR_BASE,...)) + +The outermost OVS_ACTION_ATTR_PUSH_NSH attribute is OK'ed by the +nla_for_each_nested() inside __ovs_nla_copy_actions(). The innermost +OVS_NSH_KEY_ATTR_BASE/MD1/MD2 are OK'ed by the nla_for_each_nested() +inside nsh_key_put_from_nlattr(). But nothing checks if the attribute +in the middle is OK. We don't even check that this attribute is the +OVS_KEY_ATTR_NSH. We just do a double unwrap with a pair of nla_data() +calls - first time directly while calling validate_push_nsh() and the +second time as part of the nla_for_each_nested() macro, which isn't +safe, potentially causing invalid memory access if the size of this +attribute is incorrect. The failure may not be noticed during +validation due to larger netlink buffer, but cause trouble later during +action execution where the buffer is allocated exactly to the size: + + BUG: KASAN: slab-out-of-bounds in nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + Read of size 184 at addr ffff88816459a634 by task a.out/22624 + + CPU: 8 UID: 0 PID: 22624 6.18.0-rc7+ #115 PREEMPT(voluntary) + Call Trace: + + dump_stack_lvl+0x51/0x70 + print_address_description.constprop.0+0x2c/0x390 + kasan_report+0xdd/0x110 + kasan_check_range+0x35/0x1b0 + __asan_memcpy+0x20/0x60 + nsh_hdr_from_nlattr+0x1dd/0x6a0 [openvswitch] + push_nsh+0x82/0x120 [openvswitch] + do_execute_actions+0x1405/0x2840 [openvswitch] + ovs_execute_actions+0xd5/0x3b0 [openvswitch] + ovs_packet_cmd_execute+0x949/0xdb0 [openvswitch] + genl_family_rcv_msg_doit+0x1d6/0x2b0 + genl_family_rcv_msg+0x336/0x580 + genl_rcv_msg+0x9f/0x130 + netlink_rcv_skb+0x11f/0x370 + genl_rcv+0x24/0x40 + netlink_unicast+0x73e/0xaa0 + netlink_sendmsg+0x744/0xbf0 + __sys_sendto+0x3d6/0x450 + do_syscall_64+0x79/0x2c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + +Let's add some checks that the attribute is properly sized and it's +the only one attribute inside the action. Technically, there is no +real reason for OVS_KEY_ATTR_NSH to be there, as we know that we're +pushing an NSH header already, it just creates extra nesting, but +that's how uAPI works today. So, keeping as it is. + +Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") +Reported-by: Junvy Yang +Signed-off-by: Ilya Maximets +Acked-by: Eelco Chaudron echaudro@redhat.com +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20251204105334.900379-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 836e8e705d40e..1d9a44d6216af 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2788,13 +2788,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, + return err; + } + +-static bool validate_push_nsh(const struct nlattr *attr, bool log) ++static bool validate_push_nsh(const struct nlattr *a, bool log) + { ++ struct nlattr *nsh_key = nla_data(a); + struct sw_flow_match match; + struct sw_flow_key key; + ++ /* There must be one and only one NSH header. */ ++ if (!nla_ok(nsh_key, nla_len(a)) || ++ nla_total_size(nla_len(nsh_key)) != nla_len(a) || ++ nla_type(nsh_key) != OVS_KEY_ATTR_NSH) ++ return false; ++ + ovs_match_init(&match, &key, true, NULL); +- return !nsh_key_put_from_nlattr(attr, &match, false, true, log); ++ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log); + } + + /* Return false if there are any non-masked bits set. +@@ -3351,7 +3358,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, + return -EINVAL; + } + mac_proto = MAC_PROTO_NONE; +- if (!validate_push_nsh(nla_data(a), log)) ++ if (!validate_push_nsh(a, log)) + return -EINVAL; + break; + +-- +2.51.0 + diff --git a/queue-6.6/net-sched-ets-always-remove-class-from-active-list-b.patch b/queue-6.6/net-sched-ets-always-remove-class-from-active-list-b.patch new file mode 100644 index 0000000000..41a0884de2 --- /dev/null +++ b/queue-6.6/net-sched-ets-always-remove-class-from-active-list-b.patch @@ -0,0 +1,232 @@ +From 6aca0bb3b30b4dc25e167985cc52c450a3deefcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: net/sched: ets: Always remove class from active list before deleting + in ets_qdisc_change + +From: Jamal Hadi Salim + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 9873f4ae90c3a..b732d09ede99a 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -652,7 +652,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.51.0 + diff --git a/queue-6.6/net-sched-ets-remove-drr-class-from-the-active-list-.patch b/queue-6.6/net-sched-ets-remove-drr-class-from-the-active-list-.patch new file mode 100644 index 0000000000..92568b645a --- /dev/null +++ b/queue-6.6/net-sched-ets-remove-drr-class-from-the-active-list-.patch @@ -0,0 +1,88 @@ +From bce07d0ec8482466a34c10b295df2d33b899e639 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Dec 2025 16:01:24 -0300 +Subject: net/sched: ets: Remove drr class from the active list if it changes + to strict + +From: Victor Nogueira + +[ Upstream commit b1e125ae425aba9b45252e933ca8df52a843ec70 ] + +Whenever a user issues an ets qdisc change command, transforming a +drr class into a strict one, the ets code isn't checking whether that +class was in the active list and removing it. This means that, if a +user changes a strict class (which was in the active list) back to a drr +one, that class will be added twice to the active list [1]. + +Doing so with the following commands: + +tc qdisc add dev lo root handle 1: ets bands 2 strict 1 +tc qdisc add dev lo parent 1:2 handle 20: \ + tbf rate 8bit burst 100b latency 1s +tc filter add dev lo parent 1: basic classid 1:2 +ping -c1 -W0.01 -s 56 127.0.0.1 +tc qdisc change dev lo root handle 1: ets bands 2 strict 2 +tc qdisc change dev lo root handle 1: ets bands 2 strict 1 +ping -c1 -W0.01 -s 56 127.0.0.1 + +Will trigger the following splat with list debug turned on: + +[ 59.279014][ T365] ------------[ cut here ]------------ +[ 59.279452][ T365] list_add double add: new=ffff88801d60e350, prev=ffff88801d60e350, next=ffff88801d60e2c0. +[ 59.280153][ T365] WARNING: CPU: 3 PID: 365 at lib/list_debug.c:35 __list_add_valid_or_report+0x17f/0x220 +[ 59.280860][ T365] Modules linked in: +[ 59.281165][ T365] CPU: 3 UID: 0 PID: 365 Comm: tc Not tainted 6.18.0-rc7-00105-g7e9f13163c13-dirty #239 PREEMPT(voluntary) +[ 59.281977][ T365] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 59.282391][ T365] RIP: 0010:__list_add_valid_or_report+0x17f/0x220 +[ 59.282842][ T365] Code: 89 c6 e8 d4 b7 0d ff 90 0f 0b 90 90 31 c0 e9 31 ff ff ff 90 48 c7 c7 e0 a0 22 9f 48 89 f2 48 89 c1 4c 89 c6 e8 b2 b7 0d ff 90 <0f> 0b 90 90 31 c0 e9 0f ff ff ff 48 89 f7 48 89 44 24 10 4c 89 44 +... +[ 59.288812][ T365] Call Trace: +[ 59.289056][ T365] +[ 59.289224][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.289546][ T365] ets_qdisc_change+0xd2b/0x1e80 +[ 59.289891][ T365] ? __lock_acquire+0x7e7/0x1be0 +[ 59.290223][ T365] ? __pfx_ets_qdisc_change+0x10/0x10 +[ 59.290546][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.290898][ T365] ? __mutex_trylock_common+0xda/0x240 +[ 59.291228][ T365] ? __pfx___mutex_trylock_common+0x10/0x10 +[ 59.291655][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.291993][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.292313][ T365] ? trace_contention_end+0xc8/0x110 +[ 59.292656][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293022][ T365] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 59.293351][ T365] tc_modify_qdisc+0x63a/0x1cf0 + +Fix this by always checking and removing an ets class from the active list +when changing it to strict. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/tree/net/sched/sch_ets.c?id=ce052b9402e461a9aded599f5b47e76bc727f7de#n663 + +Fixes: cd9b50adc6bb9 ("net/sched: ets: fix crash when flipping from 'strict' to 'quantum'") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Reviewed-by: Petr Machata +Link: https://patch.msgid.link/20251208190125.1868423-1-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index b732d09ede99a..6ff619277ffd9 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -664,6 +664,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nstrict; i < nstrict; i++) { ++ if (cl_is_active(&q->classes[i])) ++ list_del_init(&q->classes[i].alist); ++ } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch b/queue-6.6/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch new file mode 100644 index 0000000000..2688d875f4 --- /dev/null +++ b/queue-6.6/netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch @@ -0,0 +1,90 @@ +From 6e22db53c5f7fb68cb62355a0a747ed56d86ebf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 12:58:01 +0100 +Subject: netfilter: nf_conncount: fix leaked ct in error paths + +From: Fernando Fernandez Mancera + +[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ] + +There are some situations where ct might be leaked as error paths are +skipping the refcounted check and return immediately. In order to solve +it make sure that the check is always called. + +Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conncount.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c +index 97b631a81484d..c00b8e522c5a7 100644 +--- a/net/netfilter/nf_conncount.c ++++ b/net/netfilter/nf_conncount.c +@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net, + struct nf_conn *found_ct; + unsigned int collect = 0; + bool refcounted = false; ++ int err = 0; + + if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) + return -ENOENT; + + if (ct && nf_ct_is_confirmed(ct)) { +- if (refcounted) +- nf_ct_put(ct); +- return -EEXIST; ++ err = -EEXIST; ++ goto out_put; + } + + if ((u32)jiffies == list->last_gc) +@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net, + } + + add_new_node: +- if (WARN_ON_ONCE(list->count > INT_MAX)) +- return -EOVERFLOW; ++ if (WARN_ON_ONCE(list->count > INT_MAX)) { ++ err = -EOVERFLOW; ++ goto out_put; ++ } + + conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); +- if (conn == NULL) +- return -ENOMEM; ++ if (conn == NULL) { ++ err = -ENOMEM; ++ goto out_put; ++ } + + conn->tuple = tuple; + conn->zone = *zone; +@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net, + out_put: + if (refcounted) + nf_ct_put(ct); +- return 0; ++ return err; + } + + int nf_conncount_add_skb(struct net *net, +@@ -446,11 +450,10 @@ insert_tree(struct net *net, + + rb_link_node_rcu(&rbconn->node, parent, rbnode); + rb_insert_color(&rbconn->node, root); +- +- if (refcounted) +- nf_ct_put(ct); + } + out_unlock: ++ if (refcounted) ++ nf_ct_put(ct); + spin_unlock_bh(&nf_conncount_locks[hash]); + return count; + } +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nf_tables-allow-loads-only-when-register-i.patch b/queue-6.6/netfilter-nf_tables-allow-loads-only-when-register-i.patch new file mode 100644 index 0000000000..e7a2d98c64 --- /dev/null +++ b/queue-6.6/netfilter-nf_tables-allow-loads-only-when-register-i.patch @@ -0,0 +1,152 @@ +From d2a666a73d84b8ee921a648cdfc7c5b3ffe4bde1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 11:56:13 +0200 +Subject: netfilter: nf_tables: allow loads only when register is initialized + +From: Florian Westphal + +[ Upstream commit 14fb07130c7ddd257e30079b87499b3f89097b09 ] + +Reject rules where a load occurs from a register that has not seen a store +early in the same rule. + +commit 4c905f6740a3 ("netfilter: nf_tables: initialize registers in +nft_do_chain()") +had to add a unconditional memset to the nftables register space to avoid +leaking stack information to userspace. + +This memset shows up in benchmarks. After this change, this commit can +be reverted again. + +Note that this breaks userspace compatibility, because theoretically +you can do + + rule 1: reg2 := meta load iif, reg2 == 1 jump ... + rule 2: reg2 == 2 jump ... // read access with no store in this rule + +... after this change this is rejected. + +Neither nftables nor iptables-nft generate such rules, each rule is +always standalone. + +This resuts in a small increase of nft_ctx structure by sizeof(long). + +To cope with hypothetical rulesets like the example above one could emit +on-demand "reg[x] = 0" store when generating the datapath blob in +nf_tables_commit_chain_prepare(). + +A patch that does this is linked to below. + +For now, lets disable this. In nf_tables, a rule is the smallest +unit that can be replaced from userspace, i.e. a hypothetical ruleset +that relies on earlier initialisations of registers can't be changed +at will as register usage would need to be coordinated. + +Link: https://lore.kernel.org/netfilter-devel/20240627135330.17039-4-fw@strlen.de/ +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Stable-dep-of: a67fd55f6a09 ("netfilter: nf_tables: remove redundant chain validation on register store") +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 1 + + net/netfilter/nf_tables_api.c | 38 +++++++++++++++++++++++++++---- + 2 files changed, 35 insertions(+), 4 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 917edb4380e58..a8fcbdb37a7f9 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -221,6 +221,7 @@ struct nft_ctx { + u8 family; + u8 level; + bool report; ++ DECLARE_BITMAP(reg_inited, NFT_REG32_NUM); + }; + + enum nft_data_desc_flags { +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 7bccfb1a8a725..8b8895e4372d9 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -146,6 +146,8 @@ static void nft_ctx_init(struct nft_ctx *ctx, + ctx->report = nlmsg_report(nlh); + ctx->flags = nlh->nlmsg_flags; + ctx->seq = nlh->nlmsg_seq; ++ ++ bitmap_zero(ctx->reg_inited, NFT_REG32_NUM); + } + + static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx, +@@ -10915,8 +10917,8 @@ static int nft_validate_register_load(enum nft_registers reg, unsigned int len) + int nft_parse_register_load(const struct nft_ctx *ctx, + const struct nlattr *attr, u8 *sreg, u32 len) + { +- u32 reg; +- int err; ++ int err, invalid_reg; ++ u32 reg, next_register; + + err = nft_parse_register(attr, ®); + if (err < 0) +@@ -10926,11 +10928,36 @@ int nft_parse_register_load(const struct nft_ctx *ctx, + if (err < 0) + return err; + ++ next_register = DIV_ROUND_UP(len, NFT_REG32_SIZE) + reg; ++ ++ /* Can't happen: nft_validate_register_load() should have failed */ ++ if (WARN_ON_ONCE(next_register > NFT_REG32_NUM)) ++ return -EINVAL; ++ ++ /* find first register that did not see an earlier store. */ ++ invalid_reg = find_next_zero_bit(ctx->reg_inited, NFT_REG32_NUM, reg); ++ ++ /* invalid register within the range that we're loading from? */ ++ if (invalid_reg < next_register) ++ return -ENODATA; ++ + *sreg = reg; + return 0; + } + EXPORT_SYMBOL_GPL(nft_parse_register_load); + ++static void nft_saw_register_store(const struct nft_ctx *__ctx, ++ int reg, unsigned int len) ++{ ++ unsigned int registers = DIV_ROUND_UP(len, NFT_REG32_SIZE); ++ struct nft_ctx *ctx = (struct nft_ctx *)__ctx; ++ ++ if (WARN_ON_ONCE(len == 0 || reg < 0)) ++ return; ++ ++ bitmap_set(ctx->reg_inited, reg, registers); ++} ++ + static int nft_validate_register_store(const struct nft_ctx *ctx, + enum nft_registers reg, + const struct nft_data *data, +@@ -10952,7 +10979,7 @@ static int nft_validate_register_store(const struct nft_ctx *ctx, + return err; + } + +- return 0; ++ break; + default: + if (type != NFT_DATA_VALUE) + return -EINVAL; +@@ -10965,8 +10992,11 @@ static int nft_validate_register_store(const struct nft_ctx *ctx, + sizeof_field(struct nft_regs, data)) + return -ERANGE; + +- return 0; ++ break; + } ++ ++ nft_saw_register_store(ctx, reg, len); ++ return 0; + } + + int nft_parse_register_store(const struct nft_ctx *ctx, +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nf_tables-pass-context-structure-to-nft_pa.patch b/queue-6.6/netfilter-nf_tables-pass-context-structure-to-nft_pa.patch new file mode 100644 index 0000000000..e281183372 --- /dev/null +++ b/queue-6.6/netfilter-nf_tables-pass-context-structure-to-nft_pa.patch @@ -0,0 +1,470 @@ +From ab7faf5a67d1bc3f4761a53f5b89267655188c96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 11:56:12 +0200 +Subject: netfilter: nf_tables: pass context structure to + nft_parse_register_load + +From: Florian Westphal + +[ Upstream commit 7ea0522ef81a335c2d3a0ab1c8a4fab9a23c4a03 ] + +Mechanical transformation, no logical changes intended. + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Stable-dep-of: a67fd55f6a09 ("netfilter: nf_tables: remove redundant chain validation on register store") +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 3 ++- + net/bridge/netfilter/nft_meta_bridge.c | 2 +- + net/ipv4/netfilter/nft_dup_ipv4.c | 4 ++-- + net/ipv6/netfilter/nft_dup_ipv6.c | 4 ++-- + net/netfilter/nf_tables_api.c | 3 ++- + net/netfilter/nft_bitwise.c | 4 ++-- + net/netfilter/nft_byteorder.c | 2 +- + net/netfilter/nft_cmp.c | 6 +++--- + net/netfilter/nft_ct.c | 2 +- + net/netfilter/nft_dup_netdev.c | 2 +- + net/netfilter/nft_dynset.c | 4 ++-- + net/netfilter/nft_exthdr.c | 2 +- + net/netfilter/nft_fwd_netdev.c | 6 +++--- + net/netfilter/nft_hash.c | 2 +- + net/netfilter/nft_lookup.c | 2 +- + net/netfilter/nft_masq.c | 4 ++-- + net/netfilter/nft_meta.c | 2 +- + net/netfilter/nft_nat.c | 8 ++++---- + net/netfilter/nft_objref.c | 2 +- + net/netfilter/nft_payload.c | 2 +- + net/netfilter/nft_queue.c | 2 +- + net/netfilter/nft_range.c | 2 +- + net/netfilter/nft_redir.c | 4 ++-- + net/netfilter/nft_tproxy.c | 4 ++-- + 24 files changed, 40 insertions(+), 38 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 32606d5430605..917edb4380e58 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -254,7 +254,8 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type) + int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest); + int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); + +-int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len); ++int nft_parse_register_load(const struct nft_ctx *ctx, ++ const struct nlattr *attr, u8 *sreg, u32 len); + int nft_parse_register_store(const struct nft_ctx *ctx, + const struct nlattr *attr, u8 *dreg, + const struct nft_data *data, +diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c +index affb740c8685e..d12a221366d60 100644 +--- a/net/bridge/netfilter/nft_meta_bridge.c ++++ b/net/bridge/netfilter/nft_meta_bridge.c +@@ -142,7 +142,7 @@ static int nft_meta_bridge_set_init(const struct nft_ctx *ctx, + } + + priv->len = len; +- err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len); ++ err = nft_parse_register_load(ctx, tb[NFTA_META_SREG], &priv->sreg, len); + if (err < 0) + return err; + +diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c +index a522c3a3be523..ef5dd88107ddb 100644 +--- a/net/ipv4/netfilter/nft_dup_ipv4.c ++++ b/net/ipv4/netfilter/nft_dup_ipv4.c +@@ -40,13 +40,13 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx, + if (tb[NFTA_DUP_SREG_ADDR] == NULL) + return -EINVAL; + +- err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, ++ err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, + sizeof(struct in_addr)); + if (err < 0) + return err; + + if (tb[NFTA_DUP_SREG_DEV]) +- err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], ++ err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], + &priv->sreg_dev, sizeof(int)); + + return err; +diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c +index c82f3fdd4a65d..492a811828a71 100644 +--- a/net/ipv6/netfilter/nft_dup_ipv6.c ++++ b/net/ipv6/netfilter/nft_dup_ipv6.c +@@ -38,13 +38,13 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx, + if (tb[NFTA_DUP_SREG_ADDR] == NULL) + return -EINVAL; + +- err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, ++ err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, + sizeof(struct in6_addr)); + if (err < 0) + return err; + + if (tb[NFTA_DUP_SREG_DEV]) +- err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], ++ err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], + &priv->sreg_dev, sizeof(int)); + + return err; +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 80443b4eaeff0..7bccfb1a8a725 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -10912,7 +10912,8 @@ static int nft_validate_register_load(enum nft_registers reg, unsigned int len) + return 0; + } + +-int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len) ++int nft_parse_register_load(const struct nft_ctx *ctx, ++ const struct nlattr *attr, u8 *sreg, u32 len) + { + u32 reg; + int err; +diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c +index ca857afbf0616..7de95674fd8c4 100644 +--- a/net/netfilter/nft_bitwise.c ++++ b/net/netfilter/nft_bitwise.c +@@ -171,7 +171,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, + + priv->len = len; + +- err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg, ++ err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG], &priv->sreg, + priv->len); + if (err < 0) + return err; +@@ -365,7 +365,7 @@ static int nft_bitwise_fast_init(const struct nft_ctx *ctx, + struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); + int err; + +- err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg, ++ err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG], &priv->sreg, + sizeof(u32)); + if (err < 0) + return err; +diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c +index f6e791a681015..2f82a444d21bf 100644 +--- a/net/netfilter/nft_byteorder.c ++++ b/net/netfilter/nft_byteorder.c +@@ -139,7 +139,7 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, + + priv->len = len; + +- err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg, ++ err = nft_parse_register_load(ctx, tb[NFTA_BYTEORDER_SREG], &priv->sreg, + priv->len); + if (err < 0) + return err; +diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c +index cd4652259095c..2605f43737bc9 100644 +--- a/net/netfilter/nft_cmp.c ++++ b/net/netfilter/nft_cmp.c +@@ -83,7 +83,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + if (err < 0) + return err; + +- err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); ++ err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len); + if (err < 0) + return err; + +@@ -222,7 +222,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx, + if (err < 0) + return err; + +- err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); ++ err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len); + if (err < 0) + return err; + +@@ -323,7 +323,7 @@ static int nft_cmp16_fast_init(const struct nft_ctx *ctx, + if (err < 0) + return err; + +- err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); ++ err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c +index ab1214da99ff3..3ec63852d058f 100644 +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -608,7 +608,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, + } + + priv->len = len; +- err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len); ++ err = nft_parse_register_load(ctx, tb[NFTA_CT_SREG], &priv->sreg, len); + if (err < 0) + goto err1; + +diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c +index e5739a59ebf10..0573f96ce0791 100644 +--- a/net/netfilter/nft_dup_netdev.c ++++ b/net/netfilter/nft_dup_netdev.c +@@ -40,7 +40,7 @@ static int nft_dup_netdev_init(const struct nft_ctx *ctx, + if (tb[NFTA_DUP_SREG_DEV] == NULL) + return -EINVAL; + +- return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev, ++ return nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev, + sizeof(int)); + } + +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index a81bd69b059b3..9a0aaeed23602 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -214,7 +214,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, + return err; + } + +- err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key, ++ err = nft_parse_register_load(ctx, tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key, + set->klen); + if (err < 0) + return err; +@@ -225,7 +225,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, + if (set->dtype == NFT_DATA_VERDICT) + return -EOPNOTSUPP; + +- err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA], ++ err = nft_parse_register_load(ctx, tb[NFTA_DYNSET_SREG_DATA], + &priv->sreg_data, set->dlen); + if (err < 0) + return err; +diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c +index cfa90ab660cfe..1d4c9632072c8 100644 +--- a/net/netfilter/nft_exthdr.c ++++ b/net/netfilter/nft_exthdr.c +@@ -586,7 +586,7 @@ static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx, + priv->flags = flags; + priv->op = op; + +- return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg, ++ return nft_parse_register_load(ctx, tb[NFTA_EXTHDR_SREG], &priv->sreg, + priv->len); + } + +diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c +index fa9e4ae00b16a..42ba31dfc0359 100644 +--- a/net/netfilter/nft_fwd_netdev.c ++++ b/net/netfilter/nft_fwd_netdev.c +@@ -52,7 +52,7 @@ static int nft_fwd_netdev_init(const struct nft_ctx *ctx, + if (tb[NFTA_FWD_SREG_DEV] == NULL) + return -EINVAL; + +- return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, ++ return nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, + sizeof(int)); + } + +@@ -178,12 +178,12 @@ static int nft_fwd_neigh_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- err = nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, ++ err = nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, + sizeof(int)); + if (err < 0) + return err; + +- return nft_parse_register_load(tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr, ++ return nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr, + addr_len); + } + +diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c +index 92d47e4692046..c91f2bef58694 100644 +--- a/net/netfilter/nft_hash.c ++++ b/net/netfilter/nft_hash.c +@@ -91,7 +91,7 @@ static int nft_jhash_init(const struct nft_ctx *ctx, + + priv->len = len; + +- err = nft_parse_register_load(tb[NFTA_HASH_SREG], &priv->sreg, len); ++ err = nft_parse_register_load(ctx, tb[NFTA_HASH_SREG], &priv->sreg, len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c +index dd5441f92fdb0..aeaf6988efd67 100644 +--- a/net/netfilter/nft_lookup.c ++++ b/net/netfilter/nft_lookup.c +@@ -113,7 +113,7 @@ static int nft_lookup_init(const struct nft_ctx *ctx, + if (IS_ERR(set)) + return PTR_ERR(set); + +- err = nft_parse_register_load(tb[NFTA_LOOKUP_SREG], &priv->sreg, ++ err = nft_parse_register_load(ctx, tb[NFTA_LOOKUP_SREG], &priv->sreg, + set->klen); + if (err < 0) + return err; +diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c +index eee05394c5339..868bd4d735555 100644 +--- a/net/netfilter/nft_masq.c ++++ b/net/netfilter/nft_masq.c +@@ -51,13 +51,13 @@ static int nft_masq_init(const struct nft_ctx *ctx, + priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS])); + + if (tb[NFTA_MASQ_REG_PROTO_MIN]) { +- err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN], ++ err = nft_parse_register_load(ctx, tb[NFTA_MASQ_REG_PROTO_MIN], + &priv->sreg_proto_min, plen); + if (err < 0) + return err; + + if (tb[NFTA_MASQ_REG_PROTO_MAX]) { +- err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX], ++ err = nft_parse_register_load(ctx, tb[NFTA_MASQ_REG_PROTO_MAX], + &priv->sreg_proto_max, + plen); + if (err < 0) +diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c +index dec76d28a0ac6..8c8eb14d647b0 100644 +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -655,7 +655,7 @@ int nft_meta_set_init(const struct nft_ctx *ctx, + } + + priv->len = len; +- err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len); ++ err = nft_parse_register_load(ctx, tb[NFTA_META_SREG], &priv->sreg, len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c +index 3d3e639a7a837..6e21f72c5b574 100644 +--- a/net/netfilter/nft_nat.c ++++ b/net/netfilter/nft_nat.c +@@ -213,13 +213,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + priv->family = family; + + if (tb[NFTA_NAT_REG_ADDR_MIN]) { +- err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN], ++ err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_ADDR_MIN], + &priv->sreg_addr_min, alen); + if (err < 0) + return err; + + if (tb[NFTA_NAT_REG_ADDR_MAX]) { +- err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX], ++ err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_ADDR_MAX], + &priv->sreg_addr_max, + alen); + if (err < 0) +@@ -233,13 +233,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + + plen = sizeof_field(struct nf_nat_range, min_proto.all); + if (tb[NFTA_NAT_REG_PROTO_MIN]) { +- err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN], ++ err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_PROTO_MIN], + &priv->sreg_proto_min, plen); + if (err < 0) + return err; + + if (tb[NFTA_NAT_REG_PROTO_MAX]) { +- err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX], ++ err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_PROTO_MAX], + &priv->sreg_proto_max, + plen); + if (err < 0) +diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c +index 08a27433e2f5f..1ee17098de0c4 100644 +--- a/net/netfilter/nft_objref.c ++++ b/net/netfilter/nft_objref.c +@@ -173,7 +173,7 @@ static int nft_objref_map_init(const struct nft_ctx *ctx, + if (!(set->flags & NFT_SET_OBJECT)) + return -EINVAL; + +- err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg, ++ err = nft_parse_register_load(ctx, tb[NFTA_OBJREF_SET_SREG], &priv->sreg, + set->klen); + if (err < 0) + return err; +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index 2db38c06bedeb..7dfc5343dae46 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -984,7 +984,7 @@ static int nft_payload_set_init(const struct nft_ctx *ctx, + } + priv->csum_type = csum_type; + +- return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg, ++ return nft_parse_register_load(ctx, tb[NFTA_PAYLOAD_SREG], &priv->sreg, + priv->len); + } + +diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c +index b8ebb187814f2..344fe311878fe 100644 +--- a/net/netfilter/nft_queue.c ++++ b/net/netfilter/nft_queue.c +@@ -135,7 +135,7 @@ static int nft_queue_sreg_init(const struct nft_ctx *ctx, + struct nft_queue *priv = nft_expr_priv(expr); + int err; + +- err = nft_parse_register_load(tb[NFTA_QUEUE_SREG_QNUM], ++ err = nft_parse_register_load(ctx, tb[NFTA_QUEUE_SREG_QNUM], + &priv->sreg_qnum, sizeof(u32)); + if (err < 0) + return err; +diff --git a/net/netfilter/nft_range.c b/net/netfilter/nft_range.c +index 51ae64cd268f4..ea382f7bbd78d 100644 +--- a/net/netfilter/nft_range.c ++++ b/net/netfilter/nft_range.c +@@ -83,7 +83,7 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr + goto err2; + } + +- err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg, ++ err = nft_parse_register_load(ctx, tb[NFTA_RANGE_SREG], &priv->sreg, + desc_from.len); + if (err < 0) + goto err2; +diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c +index 9051863509f31..95eedad85c835 100644 +--- a/net/netfilter/nft_redir.c ++++ b/net/netfilter/nft_redir.c +@@ -50,13 +50,13 @@ static int nft_redir_init(const struct nft_ctx *ctx, + + plen = sizeof_field(struct nf_nat_range, min_proto.all); + if (tb[NFTA_REDIR_REG_PROTO_MIN]) { +- err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN], ++ err = nft_parse_register_load(ctx, tb[NFTA_REDIR_REG_PROTO_MIN], + &priv->sreg_proto_min, plen); + if (err < 0) + return err; + + if (tb[NFTA_REDIR_REG_PROTO_MAX]) { +- err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MAX], ++ err = nft_parse_register_load(ctx, tb[NFTA_REDIR_REG_PROTO_MAX], + &priv->sreg_proto_max, + plen); + if (err < 0) +diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c +index ed344af2a439b..50481280abd26 100644 +--- a/net/netfilter/nft_tproxy.c ++++ b/net/netfilter/nft_tproxy.c +@@ -254,14 +254,14 @@ static int nft_tproxy_init(const struct nft_ctx *ctx, + } + + if (tb[NFTA_TPROXY_REG_ADDR]) { +- err = nft_parse_register_load(tb[NFTA_TPROXY_REG_ADDR], ++ err = nft_parse_register_load(ctx, tb[NFTA_TPROXY_REG_ADDR], + &priv->sreg_addr, alen); + if (err < 0) + return err; + } + + if (tb[NFTA_TPROXY_REG_PORT]) { +- err = nft_parse_register_load(tb[NFTA_TPROXY_REG_PORT], ++ err = nft_parse_register_load(ctx, tb[NFTA_TPROXY_REG_PORT], + &priv->sreg_port, sizeof(u16)); + if (err < 0) + return err; +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nf_tables-remove-redundant-chain-validatio.patch b/queue-6.6/netfilter-nf_tables-remove-redundant-chain-validatio.patch new file mode 100644 index 0000000000..4fbd7e6c6a --- /dev/null +++ b/queue-6.6/netfilter-nf_tables-remove-redundant-chain-validatio.patch @@ -0,0 +1,59 @@ +From 5478fedf7b3b9cb61dc467b894613de7769fd32a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Nov 2025 13:42:05 +0100 +Subject: netfilter: nf_tables: remove redundant chain validation on register + store + +From: Pablo Neira Ayuso + +[ Upstream commit a67fd55f6a09f4119b7232c19e0f348fe31ab0db ] + +This validation predates the introduction of the state machine that +determines when to enter slow path validation for error reporting. + +Currently, table validation is perform when: + +- new rule contains expressions that need validation. +- new set element with jump/goto verdict. + +Validation on register store skips most checks with no basechains, still +this walks the graph searching for loops and ensuring expressions are +called from the right hook. Remove this. + +Fixes: a654de8fdc18 ("netfilter: nf_tables: fix chain dependency validation") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 8b8895e4372d9..394ee65e1d35f 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -10964,21 +10964,10 @@ static int nft_validate_register_store(const struct nft_ctx *ctx, + enum nft_data_types type, + unsigned int len) + { +- int err; +- + switch (reg) { + case NFT_REG_VERDICT: + if (type != NFT_DATA_VERDICT) + return -EINVAL; +- +- if (data != NULL && +- (data->verdict.code == NFT_GOTO || +- data->verdict.code == NFT_JUMP)) { +- err = nft_chain_validate(ctx, data->verdict.chain); +- if (err < 0) +- return err; +- } +- + break; + default: + if (type != NFT_DATA_VALUE) +-- +2.51.0 + diff --git a/queue-6.6/netrom-fix-memory-leak-in-nr_sendmsg.patch b/queue-6.6/netrom-fix-memory-leak-in-nr_sendmsg.patch new file mode 100644 index 0000000000..3daa2103b0 --- /dev/null +++ b/queue-6.6/netrom-fix-memory-leak-in-nr_sendmsg.patch @@ -0,0 +1,74 @@ +From 0544b4c981e0e614a31c261c4618e0d949197bba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 12:13:15 +0800 +Subject: netrom: Fix memory leak in nr_sendmsg() + +From: Wang Liang + +[ Upstream commit 613d12dd794e078be8ff3cf6b62a6b9acf7f4619 ] + +syzbot reported a memory leak [1]. + +When function sock_alloc_send_skb() return NULL in nr_output(), the +original skb is not freed, which was allocated in nr_sendmsg(). Fix this +by freeing it before return. + +[1] +BUG: memory leak +unreferenced object 0xffff888129f35500 (size 240): + comm "syz.0.17", pid 6119, jiffies 4294944652 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 10 52 28 81 88 ff ff ..........R(.... + backtrace (crc 1456a3e4): + kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline] + slab_post_alloc_hook mm/slub.c:4983 [inline] + slab_alloc_node mm/slub.c:5288 [inline] + kmem_cache_alloc_node_noprof+0x36f/0x5e0 mm/slub.c:5340 + __alloc_skb+0x203/0x240 net/core/skbuff.c:660 + alloc_skb include/linux/skbuff.h:1383 [inline] + alloc_skb_with_frags+0x69/0x3f0 net/core/skbuff.c:6671 + sock_alloc_send_pskb+0x379/0x3e0 net/core/sock.c:2965 + sock_alloc_send_skb include/net/sock.h:1859 [inline] + nr_sendmsg+0x287/0x450 net/netrom/af_netrom.c:1105 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg net/socket.c:742 [inline] + sock_write_iter+0x293/0x2a0 net/socket.c:1195 + new_sync_write fs/read_write.c:593 [inline] + vfs_write+0x45d/0x710 fs/read_write.c:686 + ksys_write+0x143/0x170 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xa4/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d7abc36bbbb6d7d40b58 +Tested-by: syzbot+d7abc36bbbb6d7d40b58@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20251129041315.1550766-1-wangliang74@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_out.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 5e531394a724b..2b3cbceb0b52d 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) + frontlen = skb_headroom(skb); + + while (skb->len > 0) { +- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) ++ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) { ++ kfree_skb(skb); + return; ++ } + + skb_reserve(skbn, frontlen); + +-- +2.51.0 + diff --git a/queue-6.6/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch b/queue-6.6/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch new file mode 100644 index 0000000000..65eafe1baf --- /dev/null +++ b/queue-6.6/nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch @@ -0,0 +1,37 @@ +From bfce31e49e00581d72ec016dcb193656efdca69b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Dec 2025 09:56:39 +0300 +Subject: nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() + +From: Dan Carpenter + +[ Upstream commit 885bebac9909994050bbbeed0829c727e42bd1b7 ] + +Set the error code if "transferred != sizeof(cmd)" instead of +returning success. + +Fixes: dbafc28955fa ("NFC: pn533: don't send USB data off of the stack") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aTfIJ9tZPmeUF4W1@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c +index a187f0e0b0f7d..9e079be43583e 100644 +--- a/drivers/nfc/pn533/usb.c ++++ b/drivers/nfc/pn533/usb.c +@@ -407,7 +407,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) + if (rc || (transferred != sizeof(cmd))) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); +- return rc; ++ return rc ?: -EINVAL; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); +-- +2.51.0 + diff --git a/queue-6.6/series b/queue-6.6/series index 6e3e53dce9..da37bda8cc 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -328,3 +328,33 @@ ksmbd-vfs-fix-race-on-m_flags-in-vfs_cache.patch bluetooth-btusb-add-new-vid-pid-2b89-6275-for-rtl876.patch bluetooth-btusb-add-new-vid-pid-13d3-3533-for-rtl882.patch gfs2-fix-use-of-bio_chain.patch +net-fec-err007885-workaround-for-xdp-tx-path.patch +netrom-fix-memory-leak-in-nr_sendmsg.patch +net-sched-ets-always-remove-class-from-active-list-b.patch +ipvlan-ignore-packet_loopback-in-handle_mode_l2.patch +mlxsw-spectrum_router-fix-possible-neighbour-referen.patch +mlxsw-spectrum_router-fix-neighbour-use-after-free.patch +mlxsw-spectrum_mr-fix-use-after-free-when-updating-m.patch +net-openvswitch-fix-middle-attribute-validation-in-p.patch +broadcom-b44-prevent-uninitialized-value-usage.patch +netfilter-nf_conncount-fix-leaked-ct-in-error-paths.patch +ipvs-fix-ipv4-null-ptr-deref-in-route-error-path.patch +caif-fix-integer-underflow-in-cffrml_receive.patch +net-sched-ets-remove-drr-class-from-the-active-list-.patch +nfc-pn533-fix-error-code-in-pn533_acr122_poweron_rdr.patch +netfilter-nf_tables-pass-context-structure-to-nft_pa.patch +netfilter-nf_tables-allow-loads-only-when-register-i.patch +netfilter-nf_tables-remove-redundant-chain-validatio.patch +iommufd-selftest-check-for-overflow-in-iommu_test_op.patch +ethtool-avoid-overflowing-userspace-buffer-on-stats-.patch +net-mlx5-fw-reset-clear-reset-requested-on-drain_fw_.patch +net-mlx5-drain-firmware-reset-in-shutdown-callback.patch +net-mlx5-fw_tracer-validate-format-string-parameters.patch +net-mlx5-fw_tracer-handle-escaped-percent-properly.patch +net-mlx5-skip-hotplug-check-on-sync-reset-using-hot-.patch +net-mlx5-serialize-firmware-reset-with-devlink.patch +net-handshake-duplicate-handshake-cancellations-leak.patch +net-enetc-do-not-transmit-redirected-xdp-frames-when.patch +net-hns3-using-the-num_tqps-in-the-vf-driver-to-appl.patch +net-hns3-using-the-num_tqps-to-check-whether-tqp_ind.patch +net-hns3-add-vlan-id-validation-before-using.patch -- 2.47.3