]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Wed, 12 Aug 2026 00:05:09 +0000 (20:05 -0400)
committerSasha Levin <sashal@kernel.org>
Wed, 12 Aug 2026 00:05:09 +0000 (20:05 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
459 files changed:
queue-5.10/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-5.10/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-5.10/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch [new file with mode: 0644]
queue-5.10/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch [new file with mode: 0644]
queue-5.10/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-5.10/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-5.10/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-5.10/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-5.10/net-marvell-prestera-try-to-load-previous-fw-version.patch [new file with mode: 0644]
queue-5.10/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-5.10/net-mlx5-remove-second-fw-tracer-check.patch [new file with mode: 0644]
queue-5.10/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-5.10/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-5.10/net-openvswitch-fix-kernel-doc-warnings-in-flow.c.patch [new file with mode: 0644]
queue-5.10/net-openvswitch-fix-kerneldoc-warnings.patch [new file with mode: 0644]
queue-5.10/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-5.10/net-qrtr-ns-raise-lookup-limit-to-128.patch [new file with mode: 0644]
queue-5.10/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-5.10/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-5.10/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-5.10/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-5.10/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-5.10/nfs4-take-a-reference-on-the-nfs_client-when-running.patch [new file with mode: 0644]
queue-5.10/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-5.10/sctp-extract-sctp_v4_err_handle-function-from-sctp_v.patch [new file with mode: 0644]
queue-5.10/sctp-extract-sctp_v6_err_handle-function-from-sctp_v.patch [new file with mode: 0644]
queue-5.10/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-5.10/sctp-remove-the-unessessary-hold-for-idev-in-sctp_v6.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-5.10/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-5.15/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-5.15/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-5.15/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch [new file with mode: 0644]
queue-5.15/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch [new file with mode: 0644]
queue-5.15/bnxt_en-fix-ptp-pps-setting-bug.patch [new file with mode: 0644]
queue-5.15/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-5.15/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-5.15/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-5.15/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch [new file with mode: 0644]
queue-5.15/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-5.15/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-5.15/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-5.15/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-5.15/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-5.15/net-qrtr-ns-raise-lookup-limit-to-128.patch [new file with mode: 0644]
queue-5.15/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-5.15/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-5.15/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-5.15/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-5.15/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch [new file with mode: 0644]
queue-5.15/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch [new file with mode: 0644]
queue-5.15/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-5.15/nfs4-take-a-reference-on-the-nfs_client-when-running.patch [new file with mode: 0644]
queue-5.15/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-5.15/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-5.15/selftests-ftrace-add-test-case-for-grp-only-input.patch [new file with mode: 0644]
queue-5.15/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch [new file with mode: 0644]
queue-5.15/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-5.15/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-5.15/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch [new file with mode: 0644]
queue-6.1/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-6.1/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-6.1/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch [new file with mode: 0644]
queue-6.1/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch [new file with mode: 0644]
queue-6.1/bnxt_en-fix-ptp-pps-setting-bug.patch [new file with mode: 0644]
queue-6.1/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-6.1/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-6.1/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch [new file with mode: 0644]
queue-6.1/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch [new file with mode: 0644]
queue-6.1/bpf-tcp-get-rid-of-st_bucket_done.patch [new file with mode: 0644]
queue-6.1/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch [new file with mode: 0644]
queue-6.1/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch [new file with mode: 0644]
queue-6.1/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch [new file with mode: 0644]
queue-6.1/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch [new file with mode: 0644]
queue-6.1/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-6.1/hwmon-ads7828-fix-external-vref-regulator-handling.patch [new file with mode: 0644]
queue-6.1/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch [new file with mode: 0644]
queue-6.1/hwmon-lm25066-use-i2c_get_match_data.patch [new file with mode: 0644]
queue-6.1/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch [new file with mode: 0644]
queue-6.1/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch [new file with mode: 0644]
queue-6.1/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch [new file with mode: 0644]
queue-6.1/ipvs-return-the-csum-validation-for-forward-hook.patch [new file with mode: 0644]
queue-6.1/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch [new file with mode: 0644]
queue-6.1/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-6.1/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-6.1/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-6.1/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-6.1/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-6.1/net-qrtr-ns-raise-lookup-limit-to-128.patch [new file with mode: 0644]
queue-6.1/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-6.1/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-6.1/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-6.1/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-6.1/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch [new file with mode: 0644]
queue-6.1/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch [new file with mode: 0644]
queue-6.1/netfilter-ipset-switch-ext_size-to-atomic64_t.patch [new file with mode: 0644]
queue-6.1/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-6.1/regulator-devres-add-api-for-reference-voltage-suppl.patch [new file with mode: 0644]
queue-6.1/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch [new file with mode: 0644]
queue-6.1/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-6.1/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-6.1/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/tcp-add-a-scheduling-point-in-established_get_first.patch [new file with mode: 0644]
queue-6.1/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch [new file with mode: 0644]
queue-6.1/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-6.1/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-6.1/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch [new file with mode: 0644]
queue-6.12/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch [new file with mode: 0644]
queue-6.12/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-6.12/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch [new file with mode: 0644]
queue-6.12/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-6.12/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch [new file with mode: 0644]
queue-6.12/bnxt_en-fix-ptp-pps-setting-bug.patch [new file with mode: 0644]
queue-6.12/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch [new file with mode: 0644]
queue-6.12/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch [new file with mode: 0644]
queue-6.12/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-6.12/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-6.12/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch [new file with mode: 0644]
queue-6.12/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch [new file with mode: 0644]
queue-6.12/bpf-tcp-get-rid-of-st_bucket_done.patch [new file with mode: 0644]
queue-6.12/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch [new file with mode: 0644]
queue-6.12/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch [new file with mode: 0644]
queue-6.12/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch [new file with mode: 0644]
queue-6.12/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch [new file with mode: 0644]
queue-6.12/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-6.12/devlink-fix-net-namespace-reference-leak-in-reload.patch [new file with mode: 0644]
queue-6.12/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch [new file with mode: 0644]
queue-6.12/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch [new file with mode: 0644]
queue-6.12/hwmon-ads7828-fix-external-vref-regulator-handling.patch [new file with mode: 0644]
queue-6.12/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch [new file with mode: 0644]
queue-6.12/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch [new file with mode: 0644]
queue-6.12/hwmon-ltc4282-clamp-negative-current-limits.patch [new file with mode: 0644]
queue-6.12/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch [new file with mode: 0644]
queue-6.12/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch [new file with mode: 0644]
queue-6.12/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch [new file with mode: 0644]
queue-6.12/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch [new file with mode: 0644]
queue-6.12/ipvs-return-the-csum-validation-for-forward-hook.patch [new file with mode: 0644]
queue-6.12/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch [new file with mode: 0644]
queue-6.12/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-6.12/net-hns3-fix-speed-configuration-residue-after-drive.patch [new file with mode: 0644]
queue-6.12/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-6.12/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch [new file with mode: 0644]
queue-6.12/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-6.12/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-6.12/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-6.12/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-6.12/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch [new file with mode: 0644]
queue-6.12/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-6.12/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-6.12/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-6.12/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch [new file with mode: 0644]
queue-6.12/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch [new file with mode: 0644]
queue-6.12/netfilter-ipset-switch-ext_size-to-atomic64_t.patch [new file with mode: 0644]
queue-6.12/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-6.12/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch [new file with mode: 0644]
queue-6.12/pds_core-keep-the-health-thread-stopped-during-reset.patch [new file with mode: 0644]
queue-6.12/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch [new file with mode: 0644]
queue-6.12/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-6.12/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-6.12/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch [new file with mode: 0644]
queue-6.12/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch [new file with mode: 0644]
queue-6.12/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-6.12/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-6.12/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch [new file with mode: 0644]
queue-6.12/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch [new file with mode: 0644]
queue-6.12/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch [new file with mode: 0644]
queue-6.12/xsk-require-at-least-16-bytes-of-tx-metadata.patch [new file with mode: 0644]
queue-6.18/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch [new file with mode: 0644]
queue-6.18/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-6.18/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch [new file with mode: 0644]
queue-6.18/arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch [new file with mode: 0644]
queue-6.18/arm64-dts-qcom-rename-x1e80100-to-hamoa.patch [new file with mode: 0644]
queue-6.18/arm64-dts-qcom-rename-x1p42100-to-purwa.patch [new file with mode: 0644]
queue-6.18/arm64-dts-qcom-rework-x1-based-asus-zenbook-a14-s-di.patch [new file with mode: 0644]
queue-6.18/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch [new file with mode: 0644]
queue-6.18/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-6.18/bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch [new file with mode: 0644]
queue-6.18/bnge-use-int-for-bnge_fix_rings_count-return-value.patch [new file with mode: 0644]
queue-6.18/bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch [new file with mode: 0644]
queue-6.18/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch [new file with mode: 0644]
queue-6.18/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch [new file with mode: 0644]
queue-6.18/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch [new file with mode: 0644]
queue-6.18/bnxt_en-fix-ptp-pps-setting-bug.patch [new file with mode: 0644]
queue-6.18/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch [new file with mode: 0644]
queue-6.18/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch [new file with mode: 0644]
queue-6.18/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-6.18/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-6.18/bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch [new file with mode: 0644]
queue-6.18/bpf-split-check_reg_sane_offset-in-two-parts.patch [new file with mode: 0644]
queue-6.18/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch [new file with mode: 0644]
queue-6.18/btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch [new file with mode: 0644]
queue-6.18/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch [new file with mode: 0644]
queue-6.18/btrfs-move-large-data-folios-out-of-experimental-fea.patch [new file with mode: 0644]
queue-6.18/btrfs-update-the-kconfig-string-for-config_btrfs_exp.patch [new file with mode: 0644]
queue-6.18/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-6.18/devlink-fix-net-namespace-reference-leak-in-reload.patch [new file with mode: 0644]
queue-6.18/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch [new file with mode: 0644]
queue-6.18/drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch [new file with mode: 0644]
queue-6.18/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch [new file with mode: 0644]
queue-6.18/eth-bnxt-store-rx-buffer-size-per-queue.patch [new file with mode: 0644]
queue-6.18/eth-bnxt-support-qcfg-provided-rx-page-size.patch [new file with mode: 0644]
queue-6.18/hwmon-ads7828-fix-external-vref-regulator-handling.patch [new file with mode: 0644]
queue-6.18/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch [new file with mode: 0644]
queue-6.18/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch [new file with mode: 0644]
queue-6.18/hwmon-ltc4282-clamp-negative-current-limits.patch [new file with mode: 0644]
queue-6.18/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch [new file with mode: 0644]
queue-6.18/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch [new file with mode: 0644]
queue-6.18/hwmon-pmbus-fix-type-confusion-in-notification-logic.patch [new file with mode: 0644]
queue-6.18/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch [new file with mode: 0644]
queue-6.18/hwmon-pmbus_core-use-guard-for-mutex-protection.patch [new file with mode: 0644]
queue-6.18/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch [new file with mode: 0644]
queue-6.18/ipvs-return-the-csum-validation-for-forward-hook.patch [new file with mode: 0644]
queue-6.18/net-add-bare-bone-queue-configs.patch [new file with mode: 0644]
queue-6.18/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch [new file with mode: 0644]
queue-6.18/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-6.18/net-hns3-fix-speed-configuration-residue-after-drive.patch [new file with mode: 0644]
queue-6.18/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-6.18/net-mlx5e-fix-bql-reset-on-sq-re-activation.patch [new file with mode: 0644]
queue-6.18/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch [new file with mode: 0644]
queue-6.18/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-6.18/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-6.18/net-pass-queue-rx-page-size-from-memory-provider.patch [new file with mode: 0644]
queue-6.18/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-6.18/net-reduce-indent-of-struct-netdev_queue_mgmt_ops-me.patch [new file with mode: 0644]
queue-6.18/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-6.18/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch [new file with mode: 0644]
queue-6.18/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-6.18/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-6.18/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-6.18/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch [new file with mode: 0644]
queue-6.18/net-stmmac-resume-phy-before-hardware-setup-when-ope.patch [new file with mode: 0644]
queue-6.18/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch [new file with mode: 0644]
queue-6.18/netfilter-flowtable-consolidate-xmit-path.patch [new file with mode: 0644]
queue-6.18/netfilter-ipset-switch-ext_size-to-atomic64_t.patch [new file with mode: 0644]
queue-6.18/netfilter-nf_flow_table-drop-existing-skb-dst-before.patch [new file with mode: 0644]
queue-6.18/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-6.18/ovpn-add-missing-rtnl_link_ops-get_size-callback.patch [new file with mode: 0644]
queue-6.18/ovpn-disable-ipv4-redirects-on-mp-interfaces.patch [new file with mode: 0644]
queue-6.18/ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch [new file with mode: 0644]
queue-6.18/ovpn-ensure-tcp-vars-are-initialized-first.patch [new file with mode: 0644]
queue-6.18/ovpn-fix-incorrect-use-of-rcu_access_pointer.patch [new file with mode: 0644]
queue-6.18/ovpn-hash-floated-peer-by-transport-identity-only.patch [new file with mode: 0644]
queue-6.18/ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch [new file with mode: 0644]
queue-6.18/ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch [new file with mode: 0644]
queue-6.18/ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch [new file with mode: 0644]
queue-6.18/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch [new file with mode: 0644]
queue-6.18/pds_core-keep-the-health-thread-stopped-during-reset.patch [new file with mode: 0644]
queue-6.18/pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch [new file with mode: 0644]
queue-6.18/pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch [new file with mode: 0644]
queue-6.18/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch [new file with mode: 0644]
queue-6.18/s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch [new file with mode: 0644]
queue-6.18/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-6.18/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-6.18/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch [new file with mode: 0644]
queue-6.18/selftests-sched_ext-handle-sleeping-task-affinity-ch.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch [new file with mode: 0644]
queue-6.18/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch [new file with mode: 0644]
queue-6.18/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-6.18/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-6.18/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch [new file with mode: 0644]
queue-6.18/vhost-scsi-reject-feature-changes-after-endpoint.patch [new file with mode: 0644]
queue-6.18/vhost-scsi-validate-t10-pi-scatterlist-counts.patch [new file with mode: 0644]
queue-6.18/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch [new file with mode: 0644]
queue-6.18/watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch [new file with mode: 0644]
queue-6.18/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch [new file with mode: 0644]
queue-6.18/xfs-handle-null-b_addr-in-xfs_buf_free.patch [new file with mode: 0644]
queue-6.18/xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch [new file with mode: 0644]
queue-6.18/xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch [new file with mode: 0644]
queue-6.18/xsk-pass-tx-metadata-pointer-by-reference.patch [new file with mode: 0644]
queue-6.18/xsk-require-at-least-16-bytes-of-tx-metadata.patch [new file with mode: 0644]
queue-6.18/xsk-validate-launch-time-metadata-size.patch [new file with mode: 0644]
queue-6.18/xsk-validate-metadata-when-processing-requests.patch [new file with mode: 0644]
queue-6.6/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch [new file with mode: 0644]
queue-6.6/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch [new file with mode: 0644]
queue-6.6/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-6.6/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch [new file with mode: 0644]
queue-6.6/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch [new file with mode: 0644]
queue-6.6/bnxt_en-fix-ptp-pps-setting-bug.patch [new file with mode: 0644]
queue-6.6/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-6.6/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-6.6/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch [new file with mode: 0644]
queue-6.6/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch [new file with mode: 0644]
queue-6.6/bpf-tcp-get-rid-of-st_bucket_done.patch [new file with mode: 0644]
queue-6.6/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch [new file with mode: 0644]
queue-6.6/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch [new file with mode: 0644]
queue-6.6/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch [new file with mode: 0644]
queue-6.6/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch [new file with mode: 0644]
queue-6.6/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-6.6/devlink-fix-net-namespace-reference-leak-in-reload.patch [new file with mode: 0644]
queue-6.6/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch [new file with mode: 0644]
queue-6.6/hwmon-ads7828-fix-external-vref-regulator-handling.patch [new file with mode: 0644]
queue-6.6/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch [new file with mode: 0644]
queue-6.6/hwmon-lm25066-use-i2c_get_match_data.patch [new file with mode: 0644]
queue-6.6/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch [new file with mode: 0644]
queue-6.6/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch [new file with mode: 0644]
queue-6.6/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch [new file with mode: 0644]
queue-6.6/ipvs-return-the-csum-validation-for-forward-hook.patch [new file with mode: 0644]
queue-6.6/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch [new file with mode: 0644]
queue-6.6/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-6.6/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-6.6/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch [new file with mode: 0644]
queue-6.6/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-6.6/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-6.6/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-6.6/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-6.6/net-sched-cls_api-add-filter-counter.patch [new file with mode: 0644]
queue-6.6/net-sched-cls_api-add-skip_sw-counter.patch [new file with mode: 0644]
queue-6.6/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch [new file with mode: 0644]
queue-6.6/net-sched-cls_api-fix-slab-use-after-free-in-fl_dump.patch [new file with mode: 0644]
queue-6.6/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-6.6/net-sched-make-skip_sw-actually-skip-software.patch [new file with mode: 0644]
queue-6.6/net-sched-refine-software-bypass-handling-in-tc_run.patch [new file with mode: 0644]
queue-6.6/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-6.6/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-6.6/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch [new file with mode: 0644]
queue-6.6/net-tcp-add-tcp-ao-config-and-structures.patch [new file with mode: 0644]
queue-6.6/net-tcp-prepare-tcp_md5sig_pool-for-tcp-ao.patch [new file with mode: 0644]
queue-6.6/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch [new file with mode: 0644]
queue-6.6/netfilter-ipset-switch-ext_size-to-atomic64_t.patch [new file with mode: 0644]
queue-6.6/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-6.6/regulator-devres-add-api-for-reference-voltage-suppl.patch [new file with mode: 0644]
queue-6.6/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch [new file with mode: 0644]
queue-6.6/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-6.6/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-6.6/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch [new file with mode: 0644]
queue-6.6/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch [new file with mode: 0644]
queue-6.6/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-6.6/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-6.6/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch [new file with mode: 0644]
queue-7.1/accel-amdxdna-fix-locally-exploitable-bug_on-in-amdx.patch [new file with mode: 0644]
queue-7.1/accel-amxdna-fix-page-insertion-errors-in-amdxdna_in.patch [new file with mode: 0644]
queue-7.1/alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken-f.patch [new file with mode: 0644]
queue-7.1/alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken.patch [new file with mode: 0644]
queue-7.1/alsa-usb-audio-fix-sticky-mixer-regressions-on-m-aud.patch [new file with mode: 0644]
queue-7.1/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch [new file with mode: 0644]
queue-7.1/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch [new file with mode: 0644]
queue-7.1/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch [new file with mode: 0644]
queue-7.1/arm64-dts-qcom-glymur-fix-pcie-smmu-interrupts.patch [new file with mode: 0644]
queue-7.1/arm64-dts-qcom-glymur-fix-qup-serial-engine-irqs.patch [new file with mode: 0644]
queue-7.1/arm64-dts-qcom-monaco-add-default-gic-address-cells.patch [new file with mode: 0644]
queue-7.1/arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch [new file with mode: 0644]
queue-7.1/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch [new file with mode: 0644]
queue-7.1/arm64-dts-qcom-sm8650-fix-ipa-imem-slice.patch [new file with mode: 0644]
queue-7.1/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch [new file with mode: 0644]
queue-7.1/bnge-fix-null-pointer-dereference-in-aux-device-rele.patch [new file with mode: 0644]
queue-7.1/bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch [new file with mode: 0644]
queue-7.1/bnge-use-int-for-bnge_fix_rings_count-return-value.patch [new file with mode: 0644]
queue-7.1/bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch [new file with mode: 0644]
queue-7.1/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch [new file with mode: 0644]
queue-7.1/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch [new file with mode: 0644]
queue-7.1/bnxt_en-fix-ptp-pps-setting-bug.patch [new file with mode: 0644]
queue-7.1/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch [new file with mode: 0644]
queue-7.1/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch [new file with mode: 0644]
queue-7.1/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch [new file with mode: 0644]
queue-7.1/bpf-check-sk_state-before-sk_protocol-in-bpf_tcp_-_s.patch [new file with mode: 0644]
queue-7.1/bpf-fix-netns-reference-imbalance-in-conntrack-kfunc.patch [new file with mode: 0644]
queue-7.1/bpf-preserve-pointer-state-for-commuted-arithmetic.patch [new file with mode: 0644]
queue-7.1/bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch [new file with mode: 0644]
queue-7.1/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch [new file with mode: 0644]
queue-7.1/btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch [new file with mode: 0644]
queue-7.1/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch [new file with mode: 0644]
queue-7.1/btrfs-initialize-inode-mapping-flags-for-cached-inod.patch [new file with mode: 0644]
queue-7.1/btrfs-lzo-add-error-message-for-invalid-headers.patch [new file with mode: 0644]
queue-7.1/btrfs-lzo-reject-inline-extents-without-valid-header.patch [new file with mode: 0644]
queue-7.1/btrfs-move-large-data-folios-out-of-experimental-fea.patch [new file with mode: 0644]
queue-7.1/counter-microchip-tcb-capture-fix-dt-channel-validat.patch [new file with mode: 0644]
queue-7.1/devlink-fix-net-namespace-reference-leak-in-reload.patch [new file with mode: 0644]
queue-7.1/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch [new file with mode: 0644]
queue-7.1/drm-xe-fix-memory-leak-in-exec_queue_set_hang_replay.patch [new file with mode: 0644]
queue-7.1/drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch [new file with mode: 0644]
queue-7.1/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch [new file with mode: 0644]
queue-7.1/hwmon-ads7828-fix-external-vref-regulator-handling.patch [new file with mode: 0644]
queue-7.1/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch [new file with mode: 0644]
queue-7.1/hwmon-corsair-psu-serialize-debugfs-access-against-h.patch [new file with mode: 0644]
queue-7.1/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch [new file with mode: 0644]
queue-7.1/hwmon-ltc4282-clamp-negative-current-limits.patch [new file with mode: 0644]
queue-7.1/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch [new file with mode: 0644]
queue-7.1/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch [new file with mode: 0644]
queue-7.1/hwmon-pmbus-core-avoid-race-condition-during-probe.patch [new file with mode: 0644]
queue-7.1/hwmon-pmbus-fix-type-confusion-in-notification-logic.patch [new file with mode: 0644]
queue-7.1/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch [new file with mode: 0644]
queue-7.1/hwmon-support-guard-and-scoped_guard-for-subsystem-l.patch [new file with mode: 0644]
queue-7.1/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch [new file with mode: 0644]
queue-7.1/ipvs-return-the-csum-validation-for-forward-hook.patch [new file with mode: 0644]
queue-7.1/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch [new file with mode: 0644]
queue-7.1/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch [new file with mode: 0644]
queue-7.1/net-hns3-fix-speed-configuration-residue-after-drive.patch [new file with mode: 0644]
queue-7.1/net-mlx5-fw_tracer-return-null-on-create-error.patch [new file with mode: 0644]
queue-7.1/net-mlx5e-fix-bql-reset-on-sq-re-activation.patch [new file with mode: 0644]
queue-7.1/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch [new file with mode: 0644]
queue-7.1/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch [new file with mode: 0644]
queue-7.1/net-openvswitch-check-ethernet-header-length-in-key_.patch [new file with mode: 0644]
queue-7.1/net-prestera-validate-firmware-header-length.patch [new file with mode: 0644]
queue-7.1/net-qrtr-ns-raise-lookup-limit-to-128.patch [new file with mode: 0644]
queue-7.1/net-remove-warn_on_once-from-sk_mc_loop.patch [new file with mode: 0644]
queue-7.1/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch [new file with mode: 0644]
queue-7.1/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch [new file with mode: 0644]
queue-7.1/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch [new file with mode: 0644]
queue-7.1/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch [new file with mode: 0644]
queue-7.1/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch [new file with mode: 0644]
queue-7.1/net-stmmac-resume-phy-before-hardware-setup-when-ope.patch [new file with mode: 0644]
queue-7.1/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch [new file with mode: 0644]
queue-7.1/netfilter-ipset-switch-ext_size-to-atomic64_t.patch [new file with mode: 0644]
queue-7.1/netfilter-nf_flow_table-drop-existing-skb-dst-before.patch [new file with mode: 0644]
queue-7.1/nfs-decrement-refcounts-if-allocating-nfs_free_state.patch [new file with mode: 0644]
queue-7.1/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch [new file with mode: 0644]
queue-7.1/ovpn-add-missing-rtnl_link_ops-get_size-callback.patch [new file with mode: 0644]
queue-7.1/ovpn-disable-ipv4-redirects-on-mp-interfaces.patch [new file with mode: 0644]
queue-7.1/ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch [new file with mode: 0644]
queue-7.1/ovpn-ensure-tcp-vars-are-initialized-first.patch [new file with mode: 0644]
queue-7.1/ovpn-fix-incorrect-use-of-rcu_access_pointer.patch [new file with mode: 0644]
queue-7.1/ovpn-hash-floated-peer-by-transport-identity-only.patch [new file with mode: 0644]
queue-7.1/ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch [new file with mode: 0644]
queue-7.1/ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch [new file with mode: 0644]
queue-7.1/ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch [new file with mode: 0644]
queue-7.1/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch [new file with mode: 0644]
queue-7.1/pds_core-keep-the-health-thread-stopped-during-reset.patch [new file with mode: 0644]
queue-7.1/pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch [new file with mode: 0644]
queue-7.1/pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch [new file with mode: 0644]
queue-7.1/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch [new file with mode: 0644]
queue-7.1/rqspinlock-reset-tail-when-preserving-queue-on-deadl.patch [new file with mode: 0644]
queue-7.1/s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch [new file with mode: 0644]
queue-7.1/sched_ext-don-t-enable-non-ext-tasks-in-the-sub-sche.patch [new file with mode: 0644]
queue-7.1/sched_ext-reject-setting-disallow-from-init_task-out.patch [new file with mode: 0644]
queue-7.1/sched_ext-skip-sub-disable-teardown-for-never-linked.patch [new file with mode: 0644]
queue-7.1/sctp-clear-control-chunk-transport-if-it-is-being-re.patch [new file with mode: 0644]
queue-7.1/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch [new file with mode: 0644]
queue-7.1/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch [new file with mode: 0644]
queue-7.1/selftests-sched_ext-handle-sleeping-task-affinity-ch.patch [new file with mode: 0644]
queue-7.1/series
queue-7.1/soc-aspeed-lpc-snoop-fix-usercopy-overflow-in-snoop_.patch [new file with mode: 0644]
queue-7.1/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch [new file with mode: 0644]
queue-7.1/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch [new file with mode: 0644]
queue-7.1/tls-don-t-abort-the-connection-on-signal-interrupted.patch [new file with mode: 0644]
queue-7.1/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch [new file with mode: 0644]
queue-7.1/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch [new file with mode: 0644]
queue-7.1/vhost-scsi-reject-feature-changes-after-endpoint.patch [new file with mode: 0644]
queue-7.1/vhost-scsi-validate-t10-pi-scatterlist-counts.patch [new file with mode: 0644]
queue-7.1/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch [new file with mode: 0644]
queue-7.1/vhost_iotlb-bound-map-allocation-in-add_range.patch [new file with mode: 0644]
queue-7.1/watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch [new file with mode: 0644]
queue-7.1/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch [new file with mode: 0644]
queue-7.1/xfs-handle-null-b_addr-in-xfs_buf_free.patch [new file with mode: 0644]
queue-7.1/xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch [new file with mode: 0644]
queue-7.1/xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch [new file with mode: 0644]
queue-7.1/xsk-pass-tx-metadata-pointer-by-reference.patch [new file with mode: 0644]
queue-7.1/xsk-require-at-least-16-bytes-of-tx-metadata.patch [new file with mode: 0644]
queue-7.1/xsk-validate-launch-time-metadata-size.patch [new file with mode: 0644]
queue-7.1/xsk-validate-metadata-when-processing-requests.patch [new file with mode: 0644]

diff --git a/queue-5.10/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-5.10/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..690fda1
--- /dev/null
@@ -0,0 +1,50 @@
+From f2c2e2ba9edf6d4600348efceb6363facd712015 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 21633c70fe7fe..fe63edc9886df 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -35,6 +35,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -63,6 +64,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-5.10/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-5.10/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..4b75ebd
--- /dev/null
@@ -0,0 +1,52 @@
+From 6ee612a25f6ddeec742501e8f930df76e3e253b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index ac7ddd87f188d..78275b2479df2 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -265,6 +265,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -286,8 +287,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-5.10/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch b/queue-5.10/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
new file mode 100644 (file)
index 0000000..d3e72dd
--- /dev/null
@@ -0,0 +1,57 @@
+From ba032c60e7c1eacad914ed8a0ce52f88d837b5eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:36 -0700
+Subject: bnxt_en: Disable EOP for TPA on all chips to prevent data corruption
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit c3faf548a00f4c17100cc9204746975fa46a73b9 ]
+
+EOP (End of frame padding) on the AGG ring may cause overlapping of
+zero padding at the end of one segment with the next segment's data.
+If Relaxed Ordering (RO) is enabled, the zero padding may overwrite
+valid data in the next segment and corrupt the data.  Older chips
+(P5 and older) do not automatically disable RO when EOP is enabled.
+On some ARM systems, data corruption was reported on 57508 (P5)
+chips with RO enabled.
+
+Always disable EOP on all chips on the AGG rings when TPA is enabled
+to fix the data corruption.
+
+Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 07fe6e55f28a6..f36b2bae37999 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3393,11 +3393,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+-              /* On P7, setting EOP will cause the chip to disable
+-               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
+-               * potentially higher performance with RO.
++              /* Disable EOP if TPA is enabled to prevent overlapping zero
++               * padding with the next segment's data.  On P7_PLUS, EOP will
++               * automatically disable Relaxed Ordering (RO) to prevent
++               * potential data corruption (and may degrade performance).  On
++               * older chips, RO will not be automatically disabled and may
++               * cause corruption.
+                */
+-              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++              if (!(bp->flags & BNXT_FLAG_TPA))
+                       type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+-- 
+2.53.0
+
diff --git a/queue-5.10/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch b/queue-5.10/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
new file mode 100644 (file)
index 0000000..0f4aa95
--- /dev/null
@@ -0,0 +1,66 @@
+From 88c9b3c4172d7cd56b19ea4e44a8a52f68cbc9e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Nov 2025 13:56:46 -0800
+Subject: bnxt_en: Do not set EOP on RX AGG BDs on 5760X chips
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit 30f253f8d9a01d532fdb7ec6c8a9d4c15fe29241 ]
+
+With End-of-Packet padding (EOP) set, the chip will disable Relaxed
+Ordering (RO) of TPA data packets.  A TPA segment with EOP set will be
+padded to the next cache boundary and can potentially overwrite the
+beginning bytes of the next TPA segment when RO is enabled on 5760X.
+To prevent that, the chip disables RO for TPA when EOP is set.
+
+To take advantge of RO and higher performance, do not set EOP on
+5760X chips when TPA is enabled.  Define a proper RX_BD_FLAGS_AGG_EOP
+constant to make it clear that we are setting EOP.
+
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20251126215648.1885936-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: c3faf548a00f ("bnxt_en: Disable EOP for TPA on all chips to prevent data corruption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 ++++++++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 6dd4104025297..07fe6e55f28a6 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3391,7 +3391,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+       if ((bp->flags & BNXT_FLAG_AGG_RINGS)) {
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+-                      RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
++                      RX_BD_TYPE_RX_AGG_BD;
++
++              /* On P7, setting EOP will cause the chip to disable
++               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
++               * potentially higher performance with RO.
++               */
++              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++                      type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+       }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index c2122d5cda622..1a7ff21f8cdb8 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -99,6 +99,7 @@ struct rx_bd {
+        #define RX_BD_TYPE_48B_BD_SIZE                          (2 << 4)
+        #define RX_BD_TYPE_64B_BD_SIZE                          (3 << 4)
+       #define RX_BD_FLAGS_SOP                                 (1 << 6)
++      #define RX_BD_FLAGS_AGG_EOP                             (1 << 6)
+       #define RX_BD_FLAGS_EOP                                 (1 << 7)
+       #define RX_BD_FLAGS_BUFFERS                             (3 << 8)
+        #define RX_BD_FLAGS_1_BUFFER_PACKET                     (0 << 8)
+-- 
+2.53.0
+
diff --git a/queue-5.10/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-5.10/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..b65c3f3
--- /dev/null
@@ -0,0 +1,80 @@
+From f68d64c59c42a7e3a21a22e43ad690fb810b9a9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 81a5e7622ea7d..dff22eddc885a 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1528,8 +1528,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1591,9 +1591,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-5.10/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-5.10/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..4770466
--- /dev/null
@@ -0,0 +1,74 @@
+From 196e3e2e72f167c87b14333fceb50c298ebd8915 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 058c05e7f144c..9866599171782 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -6301,11 +6301,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               break;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
+@@ -6373,7 +6374,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -7232,8 +7233,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-5.10/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-5.10/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..009bda7
--- /dev/null
@@ -0,0 +1,70 @@
+From a1796ce78148ae9006bf059b322b037d68459f34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 40d02df8acf75..822c072ffa20e 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -317,7 +317,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+@@ -352,7 +352,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-5.10/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..df2f4be
--- /dev/null
@@ -0,0 +1,42 @@
+From 576a9fce7878612b4d771f82550c91a6be59a844 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index 43f3146caf07e..18495d80e2e74 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1291,7 +1291,6 @@ static int hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-marvell-prestera-try-to-load-previous-fw-version.patch b/queue-5.10/net-marvell-prestera-try-to-load-previous-fw-version.patch
new file mode 100644 (file)
index 0000000..cbac9d8
--- /dev/null
@@ -0,0 +1,172 @@
+From f33a4801df1b07ac632666c632d3ea3dc182e5bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 May 2021 17:32:46 +0300
+Subject: net: marvell: prestera: try to load previous fw version
+
+From: Vadym Kochan <vkochan@marvell.com>
+
+[ Upstream commit 47f26018a414ff640527be4ca814168e0b71eaf3 ]
+
+Lets try to load previous fw version in case the latest one is missing on
+existing system.
+
+Signed-off-by: Vadym Kochan <vkochan@marvell.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 8ae344eb540a ("net: prestera: validate firmware header length")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/marvell/prestera/prestera_pci.c  | 83 ++++++++++++++-----
+ 1 file changed, 61 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index be5677623455c..39cd3d5010147 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -16,6 +16,9 @@
+ #define PRESTERA_SUPP_FW_MAJ_VER      2
+ #define PRESTERA_SUPP_FW_MIN_VER      0
++#define PRESTERA_PREV_FW_MAJ_VER      2
++#define PRESTERA_PREV_FW_MIN_VER      0
++
+ #define PRESTERA_FW_PATH_FMT  "mrvl/prestera/mvsw_prestera_fw-v%u.%u.img"
+ #define PRESTERA_FW_HDR_MAGIC         0x351D9D06
+@@ -166,6 +169,8 @@ struct prestera_fw_evtq {
+ };
+ struct prestera_fw {
++      struct prestera_fw_rev rev_supp;
++      const struct firmware *bin;
+       struct workqueue_struct *wq;
+       struct prestera_device dev;
+       u8 __iomem *ldr_regs;
+@@ -576,25 +581,24 @@ static void prestera_fw_rev_parse(const struct prestera_fw_header *hdr,
+ static int prestera_fw_rev_check(struct prestera_fw *fw)
+ {
+       struct prestera_fw_rev *rev = &fw->dev.fw_rev;
+-      u16 maj_supp = PRESTERA_SUPP_FW_MAJ_VER;
+-      u16 min_supp = PRESTERA_SUPP_FW_MIN_VER;
+-      if (rev->maj == maj_supp && rev->min >= min_supp)
++      if (rev->maj == fw->rev_supp.maj && rev->min >= fw->rev_supp.min)
+               return 0;
+       dev_err(fw->dev.dev, "Driver supports FW version only '%u.%u.x'",
+-              PRESTERA_SUPP_FW_MAJ_VER, PRESTERA_SUPP_FW_MIN_VER);
++              fw->rev_supp.maj, fw->rev_supp.min);
+       return -EINVAL;
+ }
+-static int prestera_fw_hdr_parse(struct prestera_fw *fw,
+-                               const struct firmware *img)
++static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+ {
+-      struct prestera_fw_header *hdr = (struct prestera_fw_header *)img->data;
+       struct prestera_fw_rev *rev = &fw->dev.fw_rev;
++      struct prestera_fw_header *hdr;
+       u32 magic;
++      hdr = (struct prestera_fw_header *)fw->bin->data;
++
+       magic = be32_to_cpu(hdr->magic_number);
+       if (magic != PRESTERA_FW_HDR_MAGIC) {
+               dev_err(fw->dev.dev, "FW img hdr magic is invalid");
+@@ -609,11 +613,52 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw,
+       return prestera_fw_rev_check(fw);
+ }
++static int prestera_fw_get(struct prestera_fw *fw)
++{
++      int ver_maj = PRESTERA_SUPP_FW_MAJ_VER;
++      int ver_min = PRESTERA_SUPP_FW_MIN_VER;
++      char fw_path[128];
++      int err;
++
++pick_fw_ver:
++      snprintf(fw_path, sizeof(fw_path), PRESTERA_FW_PATH_FMT,
++               ver_maj, ver_min);
++
++      err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev);
++      if (err) {
++              if (ver_maj == PRESTERA_SUPP_FW_MAJ_VER) {
++                      ver_maj = PRESTERA_PREV_FW_MAJ_VER;
++                      ver_min = PRESTERA_PREV_FW_MIN_VER;
++
++                      dev_warn(fw->dev.dev,
++                               "missing latest %s firmware, fall-back to previous %u.%u version\n",
++                               fw_path, ver_maj, ver_min);
++
++                      goto pick_fw_ver;
++              } else {
++                      dev_err(fw->dev.dev, "failed to request previous firmware: %s\n",
++                              fw_path);
++                      return err;
++              }
++      }
++
++      dev_info(fw->dev.dev, "Loading %s ...", fw_path);
++
++      fw->rev_supp.maj = ver_maj;
++      fw->rev_supp.min = ver_min;
++      fw->rev_supp.sub = 0;
++
++      return 0;
++}
++
++static void prestera_fw_put(struct prestera_fw *fw)
++{
++      release_firmware(fw->bin);
++}
++
+ static int prestera_fw_load(struct prestera_fw *fw)
+ {
+       size_t hlen = sizeof(struct prestera_fw_header);
+-      const struct firmware *f;
+-      char fw_path[128];
+       int err;
+       err = prestera_ldr_wait_reg32(fw, PRESTERA_LDR_READY_REG,
+@@ -632,30 +677,24 @@ static int prestera_fw_load(struct prestera_fw *fw)
+       fw->ldr_wr_idx = 0;
+-      snprintf(fw_path, sizeof(fw_path), PRESTERA_FW_PATH_FMT,
+-               PRESTERA_SUPP_FW_MAJ_VER, PRESTERA_SUPP_FW_MIN_VER);
+-
+-      err = request_firmware_direct(&f, fw_path, fw->dev.dev);
+-      if (err) {
+-              dev_err(fw->dev.dev, "failed to request firmware file\n");
++      err = prestera_fw_get(fw);
++      if (err)
+               return err;
+-      }
+-      err = prestera_fw_hdr_parse(fw, f);
++      err = prestera_fw_hdr_parse(fw);
+       if (err) {
+               dev_err(fw->dev.dev, "FW image header is invalid\n");
+               goto out_release;
+       }
+-      prestera_ldr_write(fw, PRESTERA_LDR_IMG_SIZE_REG, f->size - hlen);
++      prestera_ldr_write(fw, PRESTERA_LDR_IMG_SIZE_REG, fw->bin->size - hlen);
+       prestera_ldr_write(fw, PRESTERA_LDR_CTL_REG, PRESTERA_LDR_CTL_DL_START);
+-      dev_info(fw->dev.dev, "Loading %s ...", fw_path);
+-
+-      err = prestera_ldr_fw_send(fw, f->data + hlen, f->size - hlen);
++      err = prestera_ldr_fw_send(fw, fw->bin->data + hlen,
++                                 fw->bin->size - hlen);
+ out_release:
+-      release_firmware(f);
++      prestera_fw_put(fw);
+       return err;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-5.10/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..a4237c5
--- /dev/null
@@ -0,0 +1,134 @@
+From 786bfed5342fe96166ede365ed85c472312a89bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 a83bfdfe51325..9817de5590b56 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1036,13 +1036,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1082,7 +1080,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1093,7 +1091,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+@@ -1136,7 +1134,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Cleanup, is owner ? (%d)\n",
+@@ -1155,7 +1153,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1204,7 +1202,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-mlx5-remove-second-fw-tracer-check.patch b/queue-5.10/net-mlx5-remove-second-fw-tracer-check.patch
new file mode 100644 (file)
index 0000000..0163097
--- /dev/null
@@ -0,0 +1,58 @@
+From 46ec1c475f4f261e39c26c7f9b2bdf540545b29b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Nov 2020 14:42:45 +0200
+Subject: net/mlx5: Remove second FW tracer check
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 7e615b9978021a034124166d4fa3dc4fc0ea4b16 ]
+
+The FW tracer check is called twice, so delete one of them.
+
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Stable-dep-of: af39eb111ce6 ("net/mlx5: fw_tracer, return NULL on create error")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 2 +-
+ drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c       | 7 +------
+ 2 files changed, 2 insertions(+), 7 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 f3985421e739e..a83bfdfe51325 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1205,7 +1205,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       int err;
+       if (IS_ERR_OR_NULL(tracer))
+-              return -EINVAL;
++              return 0;
+       dev = tracer->dev;
+       mlx5_fw_tracer_cleanup(tracer);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+index a2d9904e10492..d2bf20035e20d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+@@ -208,16 +208,11 @@ static void mlx5_fw_live_patch_event(struct work_struct *work)
+       struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
+                                                     fw_live_patch_work);
+       struct mlx5_core_dev *dev = fw_reset->dev;
+-      struct mlx5_fw_tracer *tracer;
+       mlx5_core_info(dev, "Live patch updated firmware version: %d.%d.%d\n", fw_rev_maj(dev),
+                      fw_rev_min(dev), fw_rev_sub(dev));
+-      tracer = dev->tracer;
+-      if (IS_ERR_OR_NULL(tracer))
+-              return;
+-
+-      if (mlx5_fw_tracer_reload(tracer))
++      if (mlx5_fw_tracer_reload(dev->tracer))
+               mlx5_core_err(dev, "Failed to reload FW tracer\n");
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-5.10/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..8951432
--- /dev/null
@@ -0,0 +1,60 @@
+From 8dcbc65e8f0df3058b7802377b217d59e8d7f226 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index db350b8f5d88b..82b22368a540a 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-5.10/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..12a1390
--- /dev/null
@@ -0,0 +1,78 @@
+From 87c478701db0006f128b41f14e8d306dba897f5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 862d376930d79..3f8a0d05161c5 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -748,8 +748,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -769,8 +767,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -785,6 +781,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-openvswitch-fix-kernel-doc-warnings-in-flow.c.patch b/queue-5.10/net-openvswitch-fix-kernel-doc-warnings-in-flow.c.patch
new file mode 100644 (file)
index 0000000..e36314e
--- /dev/null
@@ -0,0 +1,84 @@
+From a579366685aa265dc9bca61e60a3d95f3f99b16f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Aug 2021 12:08:34 -0700
+Subject: net: openvswitch: fix kernel-doc warnings in flow.c
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit d6e712aa7e6a3d5a9633f4bcbe2237f3edc292bd ]
+
+Repair kernel-doc notation in a few places to make it conform to
+the expected format.
+
+Fixes the following kernel-doc warnings:
+
+flow.c:296: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst
+ * Parse vlan tag from vlan header.
+flow.c:296: warning: missing initial short description on line:
+ * Parse vlan tag from vlan header.
+flow.c:537: warning: No description found for return value of 'key_extract_l3l4'
+flow.c:769: warning: No description found for return value of 'key_extract'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Pravin B Shelar <pshelar@ovn.org>
+Cc: dev@openvswitch.org
+Link: https://lore.kernel.org/r/20210808190834.23362-1-rdunlap@infradead.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: cf6f8b29befb ("net/openvswitch: check Ethernet header length in key_extract()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index beacb1b46706e..862d376930d79 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -293,14 +293,14 @@ static bool icmp6hdr_ok(struct sk_buff *skb)
+ }
+ /**
+- * Parse vlan tag from vlan header.
++ * parse_vlan_tag - Parse vlan tag from vlan header.
+  * @skb: skb containing frame to parse
+  * @key_vh: pointer to parsed vlan tag
+  * @untag_vlan: should the vlan header be removed from the frame
+  *
+- * Returns ERROR on memory error.
+- * Returns 0 if it encounters a non-vlan or incomplete packet.
+- * Returns 1 after successfully parsing vlan tag.
++ * Return: ERROR on memory error.
++ * %0 if it encounters a non-vlan or incomplete packet.
++ * %1 after successfully parsing vlan tag.
+  */
+ static int parse_vlan_tag(struct sk_buff *skb, struct vlan_head *key_vh,
+                         bool untag_vlan)
+@@ -533,6 +533,7 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
+  *       L3 header
+  * @key: output flow key
+  *
++ * Return: %0 if successful, otherwise a negative errno value.
+  */
+ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+@@ -749,8 +750,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  *
+  * The caller must ensure that skb->len >= ETH_HLEN.
+  *
+- * Returns 0 if successful, otherwise a negative errno value.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -765,6 +764,8 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  *
+  *    - skb->protocol: the type of the data starting at skb->network_header.
+  *      Equals to key->eth.type.
++ *
++ * Return: %0 if successful, otherwise a negative errno value.
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-openvswitch-fix-kerneldoc-warnings.patch b/queue-5.10/net-openvswitch-fix-kerneldoc-warnings.patch
new file mode 100644 (file)
index 0000000..2d2ca7c
--- /dev/null
@@ -0,0 +1,60 @@
+From 10a238ee1e60b47a9419599f44c91a49203b8732 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Oct 2020 01:48:49 +0100
+Subject: net: openvswitch: Fix kerneldoc warnings
+
+From: Andrew Lunn <andrew@lunn.ch>
+
+[ Upstream commit 210bba6790dc150c0dd65da2cbc4de39e5fa3a74 ]
+
+net/openvswitch/flow.c:303: warning: Function parameter or member 'key_vh' not described in 'parse_vlan_tag'
+net/openvswitch/flow.c:303: warning: Function parameter or member 'skb' not described in 'parse_vlan_tag'
+net/openvswitch/flow.c:303: warning: Function parameter or member 'untag_vlan' not described in 'parse_vlan_tag'
+net/openvswitch/vport.c:122: warning: Function parameter or member 'parms' not described in 'ovs_vport_alloc'
+
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/20201028004849.930094-1-andrew@lunn.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: cf6f8b29befb ("net/openvswitch: check Ethernet header length in key_extract()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c  | 4 ++++
+ net/openvswitch/vport.c | 4 +++-
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 94531289ed26a..beacb1b46706e 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -294,6 +294,10 @@ static bool icmp6hdr_ok(struct sk_buff *skb)
+ /**
+  * Parse vlan tag from vlan header.
++ * @skb: skb containing frame to parse
++ * @key_vh: pointer to parsed vlan tag
++ * @untag_vlan: should the vlan header be removed from the frame
++ *
+  * Returns ERROR on memory error.
+  * Returns 0 if it encounters a non-vlan or incomplete packet.
+  * Returns 1 after successfully parsing vlan tag.
+diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
+index ced707ff6dd97..2c876424864d2 100644
+--- a/net/openvswitch/vport.c
++++ b/net/openvswitch/vport.c
+@@ -111,10 +111,12 @@ struct vport *ovs_vport_locate(const struct net *net, const char *name)
+  *
+  * @priv_size: Size of private data area to allocate.
+  * @ops: vport device ops
++ * @parms: information about new vport.
+  *
+  * Allocate and initialize a new vport defined by @ops.  The vport will contain
+  * a private data area of size @priv_size that can be accessed using
+- * vport_priv().  vports that are no longer needed should be released with
++ * vport_priv().  Some parameters of the vport will be initialized from @parms.
++ * @vports that are no longer needed should be released with
+  * vport_free().
+  */
+ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-prestera-validate-firmware-header-length.patch b/queue-5.10/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..21cb105
--- /dev/null
@@ -0,0 +1,42 @@
+From 4e0de47af795cb2bfa63bc29418a4b3ebdfe48e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index 39cd3d5010147..bdc57f4245930 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -597,6 +597,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-qrtr-ns-raise-lookup-limit-to-128.patch b/queue-5.10/net-qrtr-ns-raise-lookup-limit-to-128.patch
new file mode 100644 (file)
index 0000000..92fb81d
--- /dev/null
@@ -0,0 +1,51 @@
+From fd7041340a21e9e91e976363eb3cd754a5b75d88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 22:18:30 +0200
+Subject: net: qrtr: ns: Raise lookup limit to 128
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Łukasz Patron <priv.luk@gmail.com>
+
+[ Upstream commit 7fc1c937b6b37c77df4ba374c37435ab06a2e945 ]
+
+Current limit of 64 is not enough for Sony Xperia 10 VII (SM6475).
+
+After merging v6.6.142 into a downstream AOSP device, it's stuck on
+boot animation and following log spam can be observed in dmesg:
+
+E qrtr    : ctrl_cmd_new_lookup(): QRTR client node exceeds max lookup limit!
+E qrtr    : qrtr_ns_worker(): failed while handling packet from 1:16600
+
+No idea why it needs more than 64 client lookups, but it appears to
+work fine with 128 as it did when there were no limits.
+
+I don't really have a good way to investigate what it needs all
+these lookups for as most of the userspace is closed source.
+
+Fixes: 5640227d9a21 ("net: qrtr: ns: Limit the maximum number of lookups")
+Signed-off-by: Łukasz Patron <priv.luk@gmail.com>
+Link: https://patch.msgid.link/20260804201919.1148015-1-priv.luk@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/qrtr/ns.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
+index 3ebb5d39e153f..4246d21da5d14 100644
+--- a/net/qrtr/ns.c
++++ b/net/qrtr/ns.c
+@@ -77,7 +77,7 @@ struct qrtr_node {
+  */
+ #define QRTR_NS_MAX_NODES   512
+ #define QRTR_NS_MAX_SERVERS 256
+-#define QRTR_NS_MAX_LOOKUPS 64
++#define QRTR_NS_MAX_LOOKUPS 128
+ static u16 node_count;
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-5.10/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..c24ce02
--- /dev/null
@@ -0,0 +1,45 @@
+From 497379f2999453c7f76dc44c6c135b83acede912 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 963ea323362ad..b51a154ec5913 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -699,7 +699,6 @@ bool sk_mc_loop(struct sock *sk)
+               return inet6_sk(sk)->mc_loop;
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-5.10/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..150e6c4
--- /dev/null
@@ -0,0 +1,142 @@
+From 8a29fa5617bd7cce0e7f88f186e2680b5c4d8ac9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index 1ad4b3e60eb3b..695c91961e33b 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -51,6 +51,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -65,9 +66,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -80,9 +83,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -295,6 +300,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -305,6 +317,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -332,11 +349,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -551,7 +568,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-5.10/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..2ad9944
--- /dev/null
@@ -0,0 +1,50 @@
+From a1a97b7643c9e9fe3d5a13a31ea26d3d49139bf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index 45b175e53aac0..8e3010a183822 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1281,7 +1281,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ntohs(ipv6h_check->payload_len);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-5.10/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..703aea7
--- /dev/null
@@ -0,0 +1,57 @@
+From ff1e83d829b7ef011656a38c67d0c57d8446a81b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index d5ee961ca72d5..572d02bfd3eda 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1582,7 +1582,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-5.10/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-5.10/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..8445fb4
--- /dev/null
@@ -0,0 +1,50 @@
+From 976a83e5b6dc1430f134bd5ea8cab7049c145db8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index bd97e0b61e70d..c455f6a8f61ae 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10138,6 +10138,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10179,6 +10180,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-5.10/nfs4-take-a-reference-on-the-nfs_client-when-running.patch b/queue-5.10/nfs4-take-a-reference-on-the-nfs_client-when-running.patch
new file mode 100644 (file)
index 0000000..23b8735
--- /dev/null
@@ -0,0 +1,54 @@
+From 88b5017ecd162dfb0f270fbbf049a07a999ddc58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 06:24:40 -0400
+Subject: nfs4: take a reference on the nfs_client when running FREE_STATEID
+
+From: Scott Mayhew <smayhew@redhat.com>
+
+[ Upstream commit 576acc259146af848cec0940f573f7125a116b9f ]
+
+During umount, the session slot tables are freed.  If there are
+outstanding FREE_STATEID tasks, a use-after-free and slab corruption can
+occur when rpc_exit_task calls rpc_call_done -> nfs41_sequence_done ->
+nfs4_sequence_process/nfs41_sequence_free_slot.
+
+Prevent that from happening by taking a reference on the nfs_client in
+nfs41_free_stateid and putting it in nfs41_free_stateid_release.
+
+Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Stable-dep-of: cf616096a0f3 ("NFS: Pin the 'struct nfs_server' during a FREE_STATEID call")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 170e9eaf536af..bd97e0b61e70d 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10135,6 +10135,10 @@ static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata)
+ static void nfs41_free_stateid_release(void *calldata)
+ {
++      struct nfs_free_stateid_data *data = calldata;
++      struct nfs_client *clp = data->server->nfs_client;
++
++      nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10171,6 +10175,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       };
+       struct nfs_free_stateid_data *data;
+       struct rpc_task *task;
++      struct nfs_client *clp = server->nfs_client;
++
++      if (!refcount_inc_not_zero(&clp->cl_count))
++              return -EIO;
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-5.10/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-5.10/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..b9caab0
--- /dev/null
@@ -0,0 +1,54 @@
+From 744a71847e17ae65e6191745b76f9f17cce84c54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 86d86ec9d90aa..122f0a948430f 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -572,6 +572,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-5.10/sctp-extract-sctp_v4_err_handle-function-from-sctp_v.patch b/queue-5.10/sctp-extract-sctp_v4_err_handle-function-from-sctp_v.patch
new file mode 100644 (file)
index 0000000..4992dea
--- /dev/null
@@ -0,0 +1,170 @@
+From 418595e4e2b0326da7edc442ab1cc4135fa70ae2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jun 2021 14:04:59 -0400
+Subject: sctp: extract sctp_v4_err_handle function from sctp_v4_err
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit d83060759a652ccb64d7486fe38c8347b4a64048 ]
+
+This patch is to extract sctp_v4_err_handle() from sctp_v4_err() to
+only handle the icmp err after the sock lookup, and it also makes
+the code clearer.
+
+sctp_v4_err_handle() will be used in sctp over udp's err handling
+in the following patch.
+
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: af0e5cdd031f ("tls: don't abort the connection on signal-interrupted sends")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/input.c | 106 ++++++++++++++++++++++-------------------------
+ 1 file changed, 49 insertions(+), 57 deletions(-)
+
+diff --git a/net/sctp/input.c b/net/sctp/input.c
+index 3c7761199f200..731d12e8038c5 100644
+--- a/net/sctp/input.c
++++ b/net/sctp/input.c
+@@ -556,6 +556,49 @@ void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
+       sctp_transport_put(t);
+ }
++static void sctp_v4_err_handle(struct sctp_transport *t, struct sk_buff *skb,
++                             __u8 type, __u8 code, __u32 info)
++{
++      struct sctp_association *asoc = t->asoc;
++      struct sock *sk = asoc->base.sk;
++      int err = 0;
++
++      switch (type) {
++      case ICMP_PARAMETERPROB:
++              err = EPROTO;
++              break;
++      case ICMP_DEST_UNREACH:
++              if (code > NR_ICMP_UNREACH)
++                      return;
++              if (code == ICMP_FRAG_NEEDED) {
++                      sctp_icmp_frag_needed(sk, asoc, t, SCTP_TRUNC4(info));
++                      return;
++              }
++              if (code == ICMP_PROT_UNREACH) {
++                      sctp_icmp_proto_unreachable(sk, asoc, t);
++                      return;
++              }
++              err = icmp_err_convert[code].errno;
++              break;
++      case ICMP_TIME_EXCEEDED:
++              if (code == ICMP_EXC_FRAGTIME)
++                      return;
++
++              err = EHOSTUNREACH;
++              break;
++      case ICMP_REDIRECT:
++              sctp_icmp_redirect(sk, t, skb);
++      default:
++              return;
++      }
++      if (!sock_owned_by_user(sk) && inet_sk(sk)->recverr) {
++              sk->sk_err = err;
++              sk->sk_error_report(sk);
++      } else {  /* Only an error on timeout */
++              sk->sk_err_soft = err;
++      }
++}
++
+ /*
+  * This routine is called by the ICMP module when it gets some
+  * sort of error condition.  If err < 0 then the socket should
+@@ -574,22 +617,19 @@ void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
+ int sctp_v4_err(struct sk_buff *skb, __u32 info)
+ {
+       const struct iphdr *iph = (const struct iphdr *)skb->data;
+-      const int ihlen = iph->ihl * 4;
+       const int type = icmp_hdr(skb)->type;
+       const int code = icmp_hdr(skb)->code;
+-      struct sock *sk;
+-      struct sctp_association *asoc = NULL;
++      struct net *net = dev_net(skb->dev);
+       struct sctp_transport *transport;
+-      struct inet_sock *inet;
++      struct sctp_association *asoc;
+       __u16 saveip, savesctp;
+-      int err;
+-      struct net *net = dev_net(skb->dev);
++      struct sock *sk;
+       /* Fix up skb to look at the embedded net header. */
+       saveip = skb->network_header;
+       savesctp = skb->transport_header;
+       skb_reset_network_header(skb);
+-      skb_set_transport_header(skb, ihlen);
++      skb_set_transport_header(skb, iph->ihl * 4);
+       sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
+       /* Put back, the original values. */
+       skb->network_header = saveip;
+@@ -598,58 +638,10 @@ int sctp_v4_err(struct sk_buff *skb, __u32 info)
+               __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
+               return -ENOENT;
+       }
+-      /* Warning:  The sock lock is held.  Remember to call
+-       * sctp_err_finish!
+-       */
+-
+-      switch (type) {
+-      case ICMP_PARAMETERPROB:
+-              err = EPROTO;
+-              break;
+-      case ICMP_DEST_UNREACH:
+-              if (code > NR_ICMP_UNREACH)
+-                      goto out_unlock;
+-
+-              /* PMTU discovery (RFC1191) */
+-              if (ICMP_FRAG_NEEDED == code) {
+-                      sctp_icmp_frag_needed(sk, asoc, transport,
+-                                            SCTP_TRUNC4(info));
+-                      goto out_unlock;
+-              } else {
+-                      if (ICMP_PROT_UNREACH == code) {
+-                              sctp_icmp_proto_unreachable(sk, asoc,
+-                                                          transport);
+-                              goto out_unlock;
+-                      }
+-              }
+-              err = icmp_err_convert[code].errno;
+-              break;
+-      case ICMP_TIME_EXCEEDED:
+-              /* Ignore any time exceeded errors due to fragment reassembly
+-               * timeouts.
+-               */
+-              if (ICMP_EXC_FRAGTIME == code)
+-                      goto out_unlock;
+-
+-              err = EHOSTUNREACH;
+-              break;
+-      case ICMP_REDIRECT:
+-              sctp_icmp_redirect(sk, transport, skb);
+-              /* Fall through to out_unlock. */
+-      default:
+-              goto out_unlock;
+-      }
+-
+-      inet = inet_sk(sk);
+-      if (!sock_owned_by_user(sk) && inet->recverr) {
+-              sk->sk_err = err;
+-              sk->sk_error_report(sk);
+-      } else {  /* Only an error on timeout */
+-              sk->sk_err_soft = err;
+-      }
+-out_unlock:
++      sctp_v4_err_handle(transport, skb, type, code, info);
+       sctp_err_finish(sk, transport);
++
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/sctp-extract-sctp_v6_err_handle-function-from-sctp_v.patch b/queue-5.10/sctp-extract-sctp_v6_err_handle-function-from-sctp_v.patch
new file mode 100644 (file)
index 0000000..e636251
--- /dev/null
@@ -0,0 +1,137 @@
+From bbff555a08dd2d2eb658a50fba549b2e89f7dd30 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jun 2021 14:04:58 -0400
+Subject: sctp: extract sctp_v6_err_handle function from sctp_v6_err
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit f6549bd37b927655c6fecad88428a731cd8a4a34 ]
+
+This patch is to extract sctp_v6_err_handle() from sctp_v6_err() to
+only handle the icmp err after the sock lookup, and it also makes
+the code clearer.
+
+sctp_v6_err_handle() will be used in sctp over udp's err handling
+in the following patch.
+
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: af0e5cdd031f ("tls: don't abort the connection on signal-interrupted sends")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/ipv6.c | 76 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 40 insertions(+), 36 deletions(-)
+
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index 984ec00ad6384..48bd3b52d56d0 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -121,50 +121,28 @@ static struct notifier_block sctp_inet6addr_notifier = {
+       .notifier_call = sctp_inet6addr_event,
+ };
+-/* ICMP error handler. */
+-static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+-                      u8 type, u8 code, int offset, __be32 info)
++static void sctp_v6_err_handle(struct sctp_transport *t, struct sk_buff *skb,
++                             __u8 type, __u8 code, __u32 info)
+ {
+-      struct sock *sk;
+-      struct sctp_association *asoc;
+-      struct sctp_transport *transport;
++      struct sctp_association *asoc = t->asoc;
++      struct sock *sk = asoc->base.sk;
+       struct ipv6_pinfo *np;
+-      __u16 saveip, savesctp;
+-      int err, ret = 0;
+-      struct net *net = dev_net(skb->dev);
+-
+-      /* Fix up skb to look at the embedded net header. */
+-      saveip   = skb->network_header;
+-      savesctp = skb->transport_header;
+-      skb_reset_network_header(skb);
+-      skb_set_transport_header(skb, offset);
+-      sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
+-      /* Put back, the original pointers. */
+-      skb->network_header   = saveip;
+-      skb->transport_header = savesctp;
+-      if (!sk) {
+-              __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
+-              return -ENOENT;
+-      }
+-
+-      /* Warning:  The sock lock is held.  Remember to call
+-       * sctp_err_finish!
+-       */
++      int err = 0;
+       switch (type) {
+       case ICMPV6_PKT_TOOBIG:
+               if (ip6_sk_accept_pmtu(sk))
+-                      sctp_icmp_frag_needed(sk, asoc, transport, ntohl(info));
+-              goto out_unlock;
++                      sctp_icmp_frag_needed(sk, asoc, t, info);
++              return;
+       case ICMPV6_PARAMPROB:
+               if (ICMPV6_UNK_NEXTHDR == code) {
+-                      sctp_icmp_proto_unreachable(sk, asoc, transport);
+-                      goto out_unlock;
++                      sctp_icmp_proto_unreachable(sk, asoc, t);
++                      return;
+               }
+               break;
+       case NDISC_REDIRECT:
+-              sctp_icmp_redirect(sk, transport, skb);
+-              goto out_unlock;
++              sctp_icmp_redirect(sk, t, skb);
++              return;
+       default:
+               break;
+       }
+@@ -174,13 +152,39 @@ static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+       if (!sock_owned_by_user(sk) && np->recverr) {
+               sk->sk_err = err;
+               sk->sk_error_report(sk);
+-      } else {  /* Only an error on timeout */
++      } else {
+               sk->sk_err_soft = err;
+       }
++}
++
++/* ICMP error handler. */
++static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
++                     u8 type, u8 code, int offset, __be32 info)
++{
++      struct net *net = dev_net(skb->dev);
++      struct sctp_transport *transport;
++      struct sctp_association *asoc;
++      __u16 saveip, savesctp;
++      struct sock *sk;
++
++      /* Fix up skb to look at the embedded net header. */
++      saveip   = skb->network_header;
++      savesctp = skb->transport_header;
++      skb_reset_network_header(skb);
++      skb_set_transport_header(skb, offset);
++      sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
++      /* Put back, the original pointers. */
++      skb->network_header   = saveip;
++      skb->transport_header = savesctp;
++      if (!sk) {
++              __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
++              return -ENOENT;
++      }
+-out_unlock:
++      sctp_v6_err_handle(transport, skb, type, code, ntohl(info));
+       sctp_err_finish(sk, transport);
+-      return ret;
++
++      return 0;
+ }
+ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
+-- 
+2.53.0
+
diff --git a/queue-5.10/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-5.10/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..82f3e35
--- /dev/null
@@ -0,0 +1,57 @@
+From 333351595af73b55419d0fd5f7beb7fe46b84806 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 651fd41996ae1..06309c1869da0 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3316,12 +3316,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-5.10/sctp-remove-the-unessessary-hold-for-idev-in-sctp_v6.patch b/queue-5.10/sctp-remove-the-unessessary-hold-for-idev-in-sctp_v6.patch
new file mode 100644 (file)
index 0000000..9104e05
--- /dev/null
@@ -0,0 +1,68 @@
+From 7073a3ae46a9923c73357b7f4f9733a63506e2b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jun 2021 14:04:57 -0400
+Subject: sctp: remove the unessessary hold for idev in sctp_v6_err
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 237a6a2e318c1ed7429e72f2640054bdda91646f ]
+
+Same as in tcp_v6_err() and __udp6_lib_err(), there's no need to
+hold idev in sctp_v6_err(), so just call __in6_dev_get() instead.
+
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: af0e5cdd031f ("tls: don't abort the connection on signal-interrupted sends")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/ipv6.c | 12 ++----------
+ 1 file changed, 2 insertions(+), 10 deletions(-)
+
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index a9cfe4d62df83..984ec00ad6384 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -125,7 +125,6 @@ static struct notifier_block sctp_inet6addr_notifier = {
+ static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                       u8 type, u8 code, int offset, __be32 info)
+ {
+-      struct inet6_dev *idev;
+       struct sock *sk;
+       struct sctp_association *asoc;
+       struct sctp_transport *transport;
+@@ -134,8 +133,6 @@ static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+       int err, ret = 0;
+       struct net *net = dev_net(skb->dev);
+-      idev = in6_dev_get(skb->dev);
+-
+       /* Fix up skb to look at the embedded net header. */
+       saveip   = skb->network_header;
+       savesctp = skb->transport_header;
+@@ -146,9 +143,8 @@ static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+       skb->network_header   = saveip;
+       skb->transport_header = savesctp;
+       if (!sk) {
+-              __ICMP6_INC_STATS(net, idev, ICMP6_MIB_INERRORS);
+-              ret = -ENOENT;
+-              goto out;
++              __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
++              return -ENOENT;
+       }
+       /* Warning:  The sock lock is held.  Remember to call
+@@ -184,10 +180,6 @@ static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ out_unlock:
+       sctp_err_finish(sk, transport);
+-out:
+-      if (likely(idev != NULL))
+-              in6_dev_put(idev);
+-
+       return ret;
+ }
+-- 
+2.53.0
+
index d6a8f4a2424f881e911a59118f8be228947286c3..28a5dd62e1caa6d1dabf3955dda4bc4c443980df 100644 (file)
@@ -308,3 +308,33 @@ firmware-stratix10-svc-fix-memory-leaks-and-list-cor.patch
 gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch
 mount-honour-sb_nouser-in-the-new-mount-api.patch
 s390-zcrypt-fix-missing-mem-scrub-at-clear-key-impor.patch
+nfs4-take-a-reference-on-the-nfs_client-when-running.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+net-mlx5-remove-second-fw-tracer-check.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+net-openvswitch-fix-kerneldoc-warnings.patch
+net-openvswitch-fix-kernel-doc-warnings-in-flow.c.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
+bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-marvell-prestera-try-to-load-previous-fw-version.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-qrtr-ns-raise-lookup-limit-to-128.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+sctp-remove-the-unessessary-hold-for-idev-in-sctp_v6.patch
+sctp-extract-sctp_v6_err_handle-function-from-sctp_v.patch
+sctp-extract-sctp_v4_err_handle-function-from-sctp_v.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
diff --git a/queue-5.10/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-5.10/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..2ed1029
--- /dev/null
@@ -0,0 +1,45 @@
+From b91f0b707ce79341e882f8736962c4384a2c9299 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 29650fa546664..c2344a46dddda 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -430,7 +430,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-5.10/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-5.10/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..61879b1
--- /dev/null
@@ -0,0 +1,53 @@
+From 3dbbf3bf859911909e0f84ed018a252ba1f5dcd8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 5d4413fe41952..4285d25d9982d 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -20,17 +20,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-5.15/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-5.15/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..6ffef08
--- /dev/null
@@ -0,0 +1,50 @@
+From e8e17ba087e05b378b25acbac1d331ee7984a353 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 21633c70fe7fe..fe63edc9886df 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -35,6 +35,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -63,6 +64,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-5.15/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-5.15/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..c6edf8d
--- /dev/null
@@ -0,0 +1,52 @@
+From 1bb1751e7cec2b178425b82d2934839af616eb5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 8487470e2e01e..c32f3b490bb35 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -265,6 +265,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -286,8 +287,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-5.15/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch b/queue-5.15/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
new file mode 100644 (file)
index 0000000..91ff252
--- /dev/null
@@ -0,0 +1,57 @@
+From 3f4f9b4edc9ae3bcfc8c9e6bcf6d8a615fa51b0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:36 -0700
+Subject: bnxt_en: Disable EOP for TPA on all chips to prevent data corruption
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit c3faf548a00f4c17100cc9204746975fa46a73b9 ]
+
+EOP (End of frame padding) on the AGG ring may cause overlapping of
+zero padding at the end of one segment with the next segment's data.
+If Relaxed Ordering (RO) is enabled, the zero padding may overwrite
+valid data in the next segment and corrupt the data.  Older chips
+(P5 and older) do not automatically disable RO when EOP is enabled.
+On some ARM systems, data corruption was reported on 57508 (P5)
+chips with RO enabled.
+
+Always disable EOP on all chips on the AGG rings when TPA is enabled
+to fix the data corruption.
+
+Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index b512a3513e324..0b435bd3db9dc 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3602,11 +3602,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+-              /* On P7, setting EOP will cause the chip to disable
+-               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
+-               * potentially higher performance with RO.
++              /* Disable EOP if TPA is enabled to prevent overlapping zero
++               * padding with the next segment's data.  On P7_PLUS, EOP will
++               * automatically disable Relaxed Ordering (RO) to prevent
++               * potential data corruption (and may degrade performance).  On
++               * older chips, RO will not be automatically disabled and may
++               * cause corruption.
+                */
+-              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++              if (!(bp->flags & BNXT_FLAG_TPA))
+                       type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+-- 
+2.53.0
+
diff --git a/queue-5.15/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch b/queue-5.15/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
new file mode 100644 (file)
index 0000000..4c495eb
--- /dev/null
@@ -0,0 +1,66 @@
+From 59a20e85238e63ef6ae4c80bfb27766e04cbbbce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Nov 2025 13:56:46 -0800
+Subject: bnxt_en: Do not set EOP on RX AGG BDs on 5760X chips
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit 30f253f8d9a01d532fdb7ec6c8a9d4c15fe29241 ]
+
+With End-of-Packet padding (EOP) set, the chip will disable Relaxed
+Ordering (RO) of TPA data packets.  A TPA segment with EOP set will be
+padded to the next cache boundary and can potentially overwrite the
+beginning bytes of the next TPA segment when RO is enabled on 5760X.
+To prevent that, the chip disables RO for TPA when EOP is set.
+
+To take advantge of RO and higher performance, do not set EOP on
+5760X chips when TPA is enabled.  Define a proper RX_BD_FLAGS_AGG_EOP
+constant to make it clear that we are setting EOP.
+
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20251126215648.1885936-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: c3faf548a00f ("bnxt_en: Disable EOP for TPA on all chips to prevent data corruption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 ++++++++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 79aa239fa7cc4..b512a3513e324 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3600,7 +3600,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+       if ((bp->flags & BNXT_FLAG_AGG_RINGS)) {
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+-                      RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
++                      RX_BD_TYPE_RX_AGG_BD;
++
++              /* On P7, setting EOP will cause the chip to disable
++               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
++               * potentially higher performance with RO.
++               */
++              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++                      type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+       }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 56aae0d654e8a..1f844798abc4e 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -103,6 +103,7 @@ struct rx_bd {
+        #define RX_BD_TYPE_48B_BD_SIZE                          (2 << 4)
+        #define RX_BD_TYPE_64B_BD_SIZE                          (3 << 4)
+       #define RX_BD_FLAGS_SOP                                 (1 << 6)
++      #define RX_BD_FLAGS_AGG_EOP                             (1 << 6)
+       #define RX_BD_FLAGS_EOP                                 (1 << 7)
+       #define RX_BD_FLAGS_BUFFERS                             (3 << 8)
+        #define RX_BD_FLAGS_1_BUFFER_PACKET                     (0 << 8)
+-- 
+2.53.0
+
diff --git a/queue-5.15/bnxt_en-fix-ptp-pps-setting-bug.patch b/queue-5.15/bnxt_en-fix-ptp-pps-setting-bug.patch
new file mode 100644 (file)
index 0000000..205192a
--- /dev/null
@@ -0,0 +1,54 @@
+From 8b67a7d89f5d61d906942b11b2cc0049dda9febf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:37 -0700
+Subject: bnxt_en: Fix PTP PPS setting bug
+
+From: Keegan Freyhof <keegan.freyhof@broadcom.com>
+
+[ Upstream commit 80eaf88efec33ac77ed7726d066c4f2f932cc329 ]
+
+The existing driver logic is always turning on PTP_CLK_REQ_PPS
+regardless of the "on" parameter passed to bnxt_ptp_enable().
+During shutdown, PTP_CLK_REQ_PPS may be turned off and this
+bug will do the opposite and may trigger a PCIe PTM request TLP.
+On some systems this can trigger a PCIe AER.
+
+Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on"
+parameter.
+
+Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index 328ae267eba5c..e337e78c00365 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -375,12 +375,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+               return rc;
+       case PTP_CLK_REQ_PPS:
+               /* Configure PHC PPS IN */
+-              rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
++              pin_id = 0;
++              if (!on)
++                      break;
++              rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+               if (rc)
+                       return rc;
+               rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
+               if (!rc)
+-                      ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
++                      ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL;
+               return rc;
+       default:
+               netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
+-- 
+2.53.0
+
diff --git a/queue-5.15/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-5.15/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..95a426a
--- /dev/null
@@ -0,0 +1,80 @@
+From f5d8cb48043bb756b1478664478d295606e17304 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 7091b018078b2..4be2afd98ce1d 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1499,8 +1499,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1562,9 +1562,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-5.15/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-5.15/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..0c6f1b4
--- /dev/null
@@ -0,0 +1,74 @@
+From e43831d5507e770c5edbbbd08e7175b131e97d2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 5e71d58e4a300..a0163090309a4 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -7388,11 +7388,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               break;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
+@@ -7460,7 +7461,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -8319,8 +8320,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-5.15/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-5.15/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..bae632a
--- /dev/null
@@ -0,0 +1,70 @@
+From 6f384d3ac7ab59dfab784a69cf0dba87e8614991 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 2625823152ead..1195fbcd639e3 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -310,7 +310,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+@@ -345,7 +345,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-5.15/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch b/queue-5.15/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
new file mode 100644 (file)
index 0000000..150fa41
--- /dev/null
@@ -0,0 +1,50 @@
+From 6dbc5a8c76ec733dd687ef7ab1f3f30f4c8cb74c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 07:19:20 +0000
+Subject: hwmon: (corsair-psu) fix possible out-of-bounds access on missing
+ string termination
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit 36c4d73ce05d1d8896c2669eb0730d35a02a2ec1 ]
+
+In theory it could be possible that the REPLY_SIZE sized buffers for
+holding the vendor and product strings could be end up missing the null
+termination (for example by malicious hardware built on purpose)
+required by the seq_printf() call. That limits the debugfs printf calls
+to a maximum string length of REPLY_SIZE.
+
+Fixes: d115b51e0e567 ("hwmon: add Corsair PSU HID controller driver")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/anLj9gPWRoRDbQBV@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index e9518221efc4c..f96de071e9094 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -644,7 +644,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->vendor);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
+       return 0;
+ }
+@@ -654,7 +654,7 @@ static int product_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->product);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-5.15/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..25b600c
--- /dev/null
@@ -0,0 +1,42 @@
+From 02e4ccb81a608412e02140dbee90086260ccc479 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index b981b6cbe6fff..7ecc3333c8df2 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1288,7 +1288,6 @@ static int hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-5.15/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..705b945
--- /dev/null
@@ -0,0 +1,134 @@
+From e29ce88890705a04d4e2c39c8cd5d777de06eaac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 1779ff98b5892..3c0e27eb01986 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1036,13 +1036,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1082,7 +1080,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1093,7 +1091,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+@@ -1136,7 +1134,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Cleanup, is owner ? (%d)\n",
+@@ -1155,7 +1153,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1204,7 +1202,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-5.15/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..73774e5
--- /dev/null
@@ -0,0 +1,60 @@
+From b6c5958ee95b3aacc4c1ea89f0f249b80dcf62a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index db350b8f5d88b..82b22368a540a 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-5.15/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..3005519
--- /dev/null
@@ -0,0 +1,78 @@
+From 96a01c91d8bd20af07e77bf4e3e9f484d536abad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 52ba0e7721cd6..635edddbd55ff 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -749,8 +749,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -770,8 +768,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -786,6 +782,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-prestera-validate-firmware-header-length.patch b/queue-5.15/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..64223fd
--- /dev/null
@@ -0,0 +1,42 @@
+From 41117a0598512f81b4103636d1225424080fbcc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index 6bef633aa6330..94bcae9020eb7 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -616,6 +616,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-qrtr-ns-raise-lookup-limit-to-128.patch b/queue-5.15/net-qrtr-ns-raise-lookup-limit-to-128.patch
new file mode 100644 (file)
index 0000000..0927491
--- /dev/null
@@ -0,0 +1,51 @@
+From 0b7d37122ec5a9f43341094c7550673688862ec0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 22:18:30 +0200
+Subject: net: qrtr: ns: Raise lookup limit to 128
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Łukasz Patron <priv.luk@gmail.com>
+
+[ Upstream commit 7fc1c937b6b37c77df4ba374c37435ab06a2e945 ]
+
+Current limit of 64 is not enough for Sony Xperia 10 VII (SM6475).
+
+After merging v6.6.142 into a downstream AOSP device, it's stuck on
+boot animation and following log spam can be observed in dmesg:
+
+E qrtr    : ctrl_cmd_new_lookup(): QRTR client node exceeds max lookup limit!
+E qrtr    : qrtr_ns_worker(): failed while handling packet from 1:16600
+
+No idea why it needs more than 64 client lookups, but it appears to
+work fine with 128 as it did when there were no limits.
+
+I don't really have a good way to investigate what it needs all
+these lookups for as most of the userspace is closed source.
+
+Fixes: 5640227d9a21 ("net: qrtr: ns: Limit the maximum number of lookups")
+Signed-off-by: Łukasz Patron <priv.luk@gmail.com>
+Link: https://patch.msgid.link/20260804201919.1148015-1-priv.luk@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/qrtr/ns.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
+index 5220529a4c62d..4df5f0a9b7419 100644
+--- a/net/qrtr/ns.c
++++ b/net/qrtr/ns.c
+@@ -77,7 +77,7 @@ struct qrtr_node {
+  */
+ #define QRTR_NS_MAX_NODES   512
+ #define QRTR_NS_MAX_SERVERS 256
+-#define QRTR_NS_MAX_LOOKUPS 64
++#define QRTR_NS_MAX_LOOKUPS 128
+ static u16 node_count;
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-5.15/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..a377195
--- /dev/null
@@ -0,0 +1,45 @@
+From 58217cd42dc8597ff068d1ae68bc24dee1e76377 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index bf2bec10d5d6a..e5f8916aa85b8 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -724,7 +724,6 @@ bool sk_mc_loop(struct sock *sk)
+               return inet6_sk(sk)->mc_loop;
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-5.15/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..51fc9a2
--- /dev/null
@@ -0,0 +1,142 @@
+From 1c4e37d23627494abd0097d9037e1715d43caa52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index 194468d0355a1..1ce483fd30379 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -51,6 +51,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -65,9 +66,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -80,9 +83,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -295,6 +300,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -305,6 +317,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -332,11 +349,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -551,7 +568,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-5.15/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..f7be954
--- /dev/null
@@ -0,0 +1,50 @@
+From 2354b1e970b4b66ae5de41e93edb093b20d1543b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index ad2597deebab6..d94c9c11ac1e2 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1281,7 +1281,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ntohs(ipv6h_check->payload_len);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-5.15/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..e9ab554
--- /dev/null
@@ -0,0 +1,57 @@
+From f5243ee866d4472a989260b7cff7375b95cb22f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index d5ee961ca72d5..572d02bfd3eda 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1582,7 +1582,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch b/queue-5.15/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
new file mode 100644 (file)
index 0000000..95130bc
--- /dev/null
@@ -0,0 +1,71 @@
+From 5eaa1334fa42635a0bc8c0a73045deb321611132 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 09:07:01 +0200
+Subject: net/smc: fix TOCTOU race between smc_listen_out() and listener close
+
+From: Sidraya Jayagond <sidraya@linux.ibm.com>
+
+[ Upstream commit 185a4caeecabc150106deda1da170b09f2ad803f ]
+
+smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
+then acquires lock_sock_nested() only after the check passes. This
+opens a window where smc_close_active() can transition the listener
+to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
+queue, and release the lock, all between the lockless read and the
+delayed lock acquisition:
+
+  smc_listen_work (smc_hs_wq)          smc_close_active()
+  -------------------------------      -------------------------
+  release_sock(child)
+  if (sk_state == SMC_LISTEN) TRUE
+                                        lock_sock(listener)
+                                        sk_state = SMC_CLOSED
+                                        smc_close_cleanup_listen()
+                                        release_sock(listener)
+                                        flush_work(tcp_listen_work)
+  lock_sock_nested(listener)
+  smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
+
+smc_close_active() flushes only tcp_listen_work. Work items already
+dispatched onto smc_hs_wq for the CLC handshake continue running
+unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
+is never released, so the child smc_sock, its clcsock, and the
+reference all leak. A remote peer that opens TCP connections while the
+server calls close() can exhaust kernel memory.
+
+Move lock_sock_nested() to before the sk_state check so that the test
+and the enqueue are atomic under the listener lock.
+
+Fixes: fd57770dd198 ("net/smc: wait for pending work before clcsock release_sock")
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260803070701.126339-1-sidraya@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 6b60a5dd240dd..7bbb59e170a6b 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1574,11 +1574,12 @@ static void smc_listen_out(struct smc_sock *new_smc)
+               atomic_dec(&lsmc->queued_smc_hs);
+       release_sock(newsmcsk); /* lock in smc_listen_work() */
++      lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+       if (lsmc->sk.sk_state == SMC_LISTEN) {
+-              lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+               smc_accept_enqueue(&lsmc->sk, newsmcsk);
+               release_sock(&lsmc->sk);
+       } else { /* no longer listening */
++              release_sock(&lsmc->sk);
+               smc_close_non_accepted(newsmcsk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch b/queue-5.15/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
new file mode 100644 (file)
index 0000000..e92e720
--- /dev/null
@@ -0,0 +1,117 @@
+From b7fe909c6522bf50a0895cddaeb069ddc7c4f03a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:38:50 +0000
+Subject: net: thunderbolt: Tear down DMA paths before stopping the rings
+
+From: Fan XinRan <shinjiangjiang@gmail.com>
+
+[ Upstream commit 68bf02b6b4ad3f748c6db71fd77b6c0402d252f4 ]
+
+tbnet_tear_down() stops both rings and frees their frame buffers before
+calling tb_xdomain_disable_paths().  tb_ring_stop() zeroes the ring's
+descriptor base and tbnet_free_buffers() unmaps and frees the pages the
+frames sit in, so by the time __tb_path_deactivate_hop() polls the hop's
+'pending' bit, anything still in flight has nowhere to drain to.
+
+The teardown sequence has been in this order since the driver was added.
+The setup path has not: commit ff7cd07f3064 ("net: thunderbolt: Enable
+DMA paths only after rings are enabled") moved the path enable to the end
+of tbnet_connected_work() and documented why:
+
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
+        */
+
+Teardown was never updated to match, so the rings and the paths now come
+down in the same order they go up instead of in reverse.
+
+On an ASMedia ASM4242 host router the 'pending' bit then never clears:
+every teardown burns the full 500 ms timeout and
+__tb_path_deactivate_hop() returns -ETIMEDOUT.  Raising the timeout to
+5 s does not help, so the hop is not slow to drain, it never drains
+at all.
+
+The failure is invisible above the thunderbolt core.
+__tb_path_deactivate_hops() is void and only calls tb_port_warn();
+tb_path_deactivate(), tb_tunnel_deactivate() and
+__tb_disconnect_xdomain_paths() are void as well, and
+tb_disconnect_xdomain_paths() ends in an unconditional "return 0".  So
+tb_xdomain_disable_paths() reports success and the netdev_warn() below
+it never fires.  Repeated teardowns eventually take the XDomain control
+channel down, after which the peer node is gone and only a power cycle
+brings the controller back.
+
+Deactivating the paths first fixes it.  Measured with kretprobes on a
+stock v6.17 tree with no other patches applied, on a link that was up
+and had just carried traffic:
+
+  before: __tb_path_deactivate_hop() returns 0 for the first hop, then
+          -ETIMEDOUT for the second 500335 us later
+  after:  0 for both, 525 us apart
+
+Alternating the two orderings ABBA over three load levels, four
+teardowns per arm: every teardown failed before the change (21 of 21
+that ran), none failed after (0 of 24).  The before arms ran short
+because the link died partway through.  The same split shows up when
+the interface is enslaved to a bond instead of just brought down, which
+is how I ran into this in the first place.  Throughput and latency after
+the change are unchanged.
+
+Hosts whose routers drain the hop despite the stale descriptor base see
+no functional difference, since the paths end up deactivated either way.
+
+Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
+Signed-off-by: Fan XinRan <shinjiangjiang@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260803-b4-tbnet-teardown-v2-1-27de6a13ca2d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
+index ba9f7062f5a7d..53d56cc860cd2 100644
+--- a/drivers/net/thunderbolt.c
++++ b/drivers/net/thunderbolt.c
+@@ -373,11 +373,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+                               break;
+               }
+-              tb_ring_stop(net->rx_ring.ring);
+-              tb_ring_stop(net->tx_ring.ring);
+-              tbnet_free_buffers(&net->rx_ring);
+-              tbnet_free_buffers(&net->tx_ring);
+-
++              /* Tear the paths down before stopping the rings.  This mirrors
++               * tbnet_connected_work(), which enables the paths last so the
++               * Rx ring is primed before packets can arrive.  Stopping a
++               * ring zeroes its descriptor base and tbnet_free_buffers()
++               * unmaps and frees the frame buffers, leaving anything still
++               * in flight with nowhere to drain to;
++               * __tb_path_deactivate_hop() then waits for the hop's
++               * 'pending' bit, which on some host routers never clears in
++               * that state.
++               */
+               ret = tb_xdomain_disable_paths(net->xd,
+                                              net->local_transmit_path,
+                                              net->tx_ring.ring->hop,
+@@ -386,6 +391,11 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+               if (ret)
+                       netdev_warn(net->dev, "failed to disable DMA paths\n");
++              tb_ring_stop(net->rx_ring.ring);
++              tb_ring_stop(net->tx_ring.ring);
++              tbnet_free_buffers(&net->rx_ring);
++              tbnet_free_buffers(&net->tx_ring);
++
+               tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+               net->remote_transmit_path = 0;
+       }
+-- 
+2.53.0
+
diff --git a/queue-5.15/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-5.15/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..81e6fd1
--- /dev/null
@@ -0,0 +1,50 @@
+From efa14b8975e450782e29525d1bad8c72ba856f55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 41bbc9407680f..25aaae1d6345e 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10297,6 +10297,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10338,6 +10339,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-5.15/nfs4-take-a-reference-on-the-nfs_client-when-running.patch b/queue-5.15/nfs4-take-a-reference-on-the-nfs_client-when-running.patch
new file mode 100644 (file)
index 0000000..957c18e
--- /dev/null
@@ -0,0 +1,54 @@
+From 6ed2d86d2ae1c17adc72b46f8086d495bb3a1ce1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 06:24:40 -0400
+Subject: nfs4: take a reference on the nfs_client when running FREE_STATEID
+
+From: Scott Mayhew <smayhew@redhat.com>
+
+[ Upstream commit 576acc259146af848cec0940f573f7125a116b9f ]
+
+During umount, the session slot tables are freed.  If there are
+outstanding FREE_STATEID tasks, a use-after-free and slab corruption can
+occur when rpc_exit_task calls rpc_call_done -> nfs41_sequence_done ->
+nfs4_sequence_process/nfs41_sequence_free_slot.
+
+Prevent that from happening by taking a reference on the nfs_client in
+nfs41_free_stateid and putting it in nfs41_free_stateid_release.
+
+Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Stable-dep-of: cf616096a0f3 ("NFS: Pin the 'struct nfs_server' during a FREE_STATEID call")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index cd97312860ce6..41bbc9407680f 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10294,6 +10294,10 @@ static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata)
+ static void nfs41_free_stateid_release(void *calldata)
+ {
++      struct nfs_free_stateid_data *data = calldata;
++      struct nfs_client *clp = data->server->nfs_client;
++
++      nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10330,6 +10334,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       };
+       struct nfs_free_stateid_data *data;
+       struct rpc_task *task;
++      struct nfs_client *clp = server->nfs_client;
++
++      if (!refcount_inc_not_zero(&clp->cl_count))
++              return -EIO;
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-5.15/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-5.15/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..a684ec2
--- /dev/null
@@ -0,0 +1,54 @@
+From 47087644103d60ae0a5837e7cf6f9d5bf2509258 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 4dd36c8375507..4a79e855c85cd 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -575,6 +575,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-5.15/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-5.15/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..1b5f677
--- /dev/null
@@ -0,0 +1,57 @@
+From b08f944054f473e96eccc65cc045e6740c3ba46f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 837fb8280bfd5..6d738f95aff1d 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3362,12 +3362,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-5.15/selftests-ftrace-add-test-case-for-grp-only-input.patch b/queue-5.15/selftests-ftrace-add-test-case-for-grp-only-input.patch
new file mode 100644 (file)
index 0000000..0fe17c9
--- /dev/null
@@ -0,0 +1,68 @@
+From 1027ded263b9c11d589922e595e132057622ae0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jun 2022 10:19:08 +0800
+Subject: selftests/ftrace: Add test case for GRP/ only input
+
+From: Linyu Yuan <quic_linyyuan@quicinc.com>
+
+[ Upstream commit 5db19792f0660ad1ece247829bddd24bb2f8db25 ]
+
+Add kprobe and eprobe event test for new GRP/ only format.
+
+Link: https://lore.kernel.org/all/1656296348-16111-5-git-send-email-quic_linyyuan@quicinc.com/
+
+Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Reviewed-by: Tom Zanussi <zanussi@kernel.org>
+Signed-off-by: Linyu Yuan <quic_linyyuan@quicinc.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Stable-dep-of: 6e3abef2a27e ("selftests/ftrace: refactor eprobes test to fix argument checks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc          | 9 ++++++++-
+ .../ftrace/test.d/dynevent/add_remove_kprobe.tc          | 7 +++++++
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index 60c02b482be83..c300eb0202620 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,7 +1,7 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "e[:[<group>/]<event>] <attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+@@ -87,4 +87,11 @@ echo "-:eprobes/$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+ ! test -d events/eprobes/$EPROBE
++if grep -q "e\[:\[<group>/]\[<event>]]" README; then
++      echo "e:mygroup/ $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
++      test -d events/mygroup
++      echo "-:mygroup/" >> dynamic_events
++      ! test -d events/mygroup
++fi
++
+ clear_trace
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc
+index b4da41d126d58..13d43f40a6fc6 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc
+@@ -23,4 +23,11 @@ grep -q myevent1 dynamic_events
+ echo > dynamic_events
++if grep -q "p\[:\[<group>/]\[<event>]]" README; then
++      echo "p:mygroup/ $PLACE" >> dynamic_events
++      test -d events/mygroup
++      echo "-:mygroup/" >> dynamic_events
++      ! test -d events/mygroup
++fi
++
+ clear_trace
+-- 
+2.53.0
+
diff --git a/queue-5.15/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch b/queue-5.15/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
new file mode 100644 (file)
index 0000000..cd122f2
--- /dev/null
@@ -0,0 +1,88 @@
+From 334fc362a7659923df346db5a29a0e21b2f13187 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 21:46:35 +0200
+Subject: selftests/ftrace: refactor eprobes test to fix argument checks
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+[ Upstream commit 6e3abef2a27e7402a94111c9eff85d887e64a309 ]
+
+The add/remove eprobe test installs an eprobe for the openat syscall and
+runs ls. It checks the filenames that were opened by ls against a
+whitelist and a blacklist.
+
+Commit 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING
+pointer") fixed access to some string fields in eprobes. This triggers
+test failures as the blacklist does not allow relative paths for the
+openat parameters.
+
+What makes this test unstable is the fact that the openat calls vary a
+lot between different systems.
+
+Refactor the test to make it more robust. "cd <directory>" will issue a
+chdir syscall with the target directory as parameter. Set an eprobe on
+the sys_enter_chdir event and filter for the exact directory name. Allow
+(fault) as fallback.
+
+Link: https://lore.kernel.org/all/20260804194705.760893-1-martin@kaiser.cx/
+
+Fixes: 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING pointer")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202607151010.b68428e1-lkp@intel.com
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc  | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index c300eb0202620..e2322693d0c32 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,16 +1,16 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+ clear_dynamic_events
+ SYSTEM="syscalls"
+-EVENT="sys_enter_openat"
++EVENT="sys_enter_chdir"
+ FIELD="filename"
+-EPROBE="eprobe_open"
++EPROBE="eprobe_chdir"
+ OPTIONS="file=+0(\$filename):ustring"
+ echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+@@ -18,20 +18,14 @@ grep -q "$EPROBE" dynamic_events
+ test -d events/eprobes/$EPROBE
+ echo 1 > events/eprobes/$EPROBE/enable
+-ls
++cd /sys/kernel/tracing
+ echo 0 > events/eprobes/$EPROBE/enable
+-content=`grep '^ *ls-' trace | grep 'file='`
+-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
+-
++content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
+ if [ -z "$content" ]; then
+       exit_fail
+ fi
+-if [ ! -z "$nocontent" ]; then
+-      exit_fail
+-fi
+-
+ echo "-:$EPROBE" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+-- 
+2.53.0
+
index 3651ff94c5d0cb24be9807e45581c5cfa4ba6c88..2659fdafc45dbab652353ac236975d70a94a0d75 100644 (file)
@@ -365,3 +365,34 @@ firmware-stratix10-svc-fix-memory-leaks-and-list-cor.patch
 gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch
 mount-honour-sb_nouser-in-the-new-mount-api.patch
 s390-zcrypt-fix-missing-mem-scrub-at-clear-key-impor.patch
+nfs4-take-a-reference-on-the-nfs_client-when-running.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+selftests-ftrace-add-test-case-for-grp-only-input.patch
+selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
+bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
+bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
+bnxt_en-fix-ptp-pps-setting-bug.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
+net-qrtr-ns-raise-lookup-limit-to-128.patch
+net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
+hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
diff --git a/queue-5.15/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch b/queue-5.15/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
new file mode 100644 (file)
index 0000000..12cf866
--- /dev/null
@@ -0,0 +1,72 @@
+From b2b3a9f29049b94855df062394e9d7824c836153 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:17:38 +0800
+Subject: tcp: fix TFO max_qlen accounting across reuseport migration
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit a0ab2ba83e35159d81cec830a92e885ecf8139be ]
+
+A listener's TCP_FASTOPEN max_qlen stops being accurate and lets through
+far more pending Fast Open requests than it was configured for.
+
+This only shows up with SO_REUSEPORT listener migration, where closing a
+listener hands its still-pending TFO children over to a surviving one.
+
+fastopenq.qlen is charged in tcp_fastopen_create_child() when the child
+is created and uncharged in reqsk_fastopen_remove() when the handshake
+completes.  The uncharge follows rsk_listener of the request the child
+points at, and inet_reqsk_clone() has repointed the child at a new
+request owned by the new listener, so the ++ and the -- land on two
+different sockets.  The new listener's qlen drifts negative and its
+limit no longer binds.
+
+Charge the new listener during migration, like reqsk_queue_migrated()
+already does for queue->young and queue->qlen.
+
+Fixes: 54b92e841937 ("tcp: Migrate TCP_ESTABLISHED/TCP_SYN_RECV sockets in accept queues.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260803061739.134737-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index d99fed07b024f..042982aaf9704 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -750,11 +750,23 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
+       nreq->rsk_listener = sk;
+-      /* We need not acquire fastopenq->lock
+-       * because the child socket is locked in inet_csk_listen_stop().
+-       */
+-      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
++      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener) {
++              struct fastopen_queue *fastopenq;
++
++              /* reqsk_fastopen_remove() will uncharge nreq->rsk_listener,
++               * that is @sk, so charge it here.  Unlike the listener
++               * being closed, @sk is live and needs its lock.
++               */
++              fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
++              spin_lock_bh(&fastopenq->lock);
++              fastopenq->qlen++;
++              spin_unlock_bh(&fastopenq->lock);
++
++              /* We need not acquire fastopenq->lock
++               * because the child socket is locked in inet_csk_listen_stop().
++               */
+               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
++      }
+       return nreq;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-5.15/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..beeba31
--- /dev/null
@@ -0,0 +1,45 @@
+From 5cec22ef9eab45369103a8c7a53aff760bd5abcf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 0cdc9131aff22..012ff6a496697 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -455,7 +455,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-5.15/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-5.15/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..81efcb8
--- /dev/null
@@ -0,0 +1,53 @@
+From 92a63ad90e252b5b91da77094278b14b572d2f0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 8f47d07c49fb7..e2c7d6d8986c3 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -20,17 +20,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-5.15/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch b/queue-5.15/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
new file mode 100644 (file)
index 0000000..8bbfc43
--- /dev/null
@@ -0,0 +1,56 @@
+From c4b54f0ea4f35790510c2a46681f91cabe973517 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:02:02 -0700
+Subject: vhost/vdpa: reject overflowing PA map page counts on 32-bit
+
+From: Yousef Alhouseen <alhouseenyousef@gmail.com>
+
+[ Upstream commit 0619aaa34c0c2a2dcb07f0e9c8a34e7efb8c4cdf ]
+
+vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
+size before computing the number of pages to pin. On 32-bit systems,
+where unsigned long is narrower than u64, that addition can overflow and
+the code can pin and map fewer pages than the requested IOTLB range.
+
+Reject sizes that overflow the unsigned long page-count calculation.
+
+Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and vhost_vdpa_pa_unmap()")
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index 17907e61f8e0c..080413757eea3 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -717,6 +717,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       unsigned int gup_flags = FOLL_LONGTERM;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
++      unsigned long page_offset;
+       u64 start = iova;
+       long pinned;
+       int ret = 0;
+@@ -729,7 +730,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       if (perm & VHOST_ACCESS_WO)
+               gup_flags |= FOLL_WRITE;
+-      npages = PFN_UP(size + (iova & ~PAGE_MASK));
++      page_offset = iova & ~PAGE_MASK;
++      if (size > ULONG_MAX - page_offset) {
++              ret = -EINVAL;
++              goto free;
++      }
++
++      npages = PFN_UP(size + page_offset);
+       if (!npages) {
+               ret = -EINVAL;
+               goto free;
+-- 
+2.53.0
+
diff --git a/queue-6.1/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-6.1/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..7a38c7e
--- /dev/null
@@ -0,0 +1,50 @@
+From f0f491009a617fcc8cb2b81635d364c2e49d9a42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 21633c70fe7fe..fe63edc9886df 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -35,6 +35,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -63,6 +64,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-6.1/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-6.1/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..262f0bb
--- /dev/null
@@ -0,0 +1,52 @@
+From 44f559ea20bcc124135c8986e70c04eaf5fb6b81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 8487470e2e01e..c32f3b490bb35 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -265,6 +265,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -286,8 +287,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-6.1/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch b/queue-6.1/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
new file mode 100644 (file)
index 0000000..241ff8c
--- /dev/null
@@ -0,0 +1,57 @@
+From 02148f889fe85a08046145deeacff8581e5e3181 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:36 -0700
+Subject: bnxt_en: Disable EOP for TPA on all chips to prevent data corruption
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit c3faf548a00f4c17100cc9204746975fa46a73b9 ]
+
+EOP (End of frame padding) on the AGG ring may cause overlapping of
+zero padding at the end of one segment with the next segment's data.
+If Relaxed Ordering (RO) is enabled, the zero padding may overwrite
+valid data in the next segment and corrupt the data.  Older chips
+(P5 and older) do not automatically disable RO when EOP is enabled.
+On some ARM systems, data corruption was reported on 57508 (P5)
+chips with RO enabled.
+
+Always disable EOP on all chips on the AGG rings when TPA is enabled
+to fix the data corruption.
+
+Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index f11ca14c5c4d3..f69ad1ffc0c9d 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3766,11 +3766,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+-              /* On P7, setting EOP will cause the chip to disable
+-               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
+-               * potentially higher performance with RO.
++              /* Disable EOP if TPA is enabled to prevent overlapping zero
++               * padding with the next segment's data.  On P7_PLUS, EOP will
++               * automatically disable Relaxed Ordering (RO) to prevent
++               * potential data corruption (and may degrade performance).  On
++               * older chips, RO will not be automatically disabled and may
++               * cause corruption.
+                */
+-              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++              if (!(bp->flags & BNXT_FLAG_TPA))
+                       type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+-- 
+2.53.0
+
diff --git a/queue-6.1/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch b/queue-6.1/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
new file mode 100644 (file)
index 0000000..4e38575
--- /dev/null
@@ -0,0 +1,66 @@
+From 8c84e7921b8869be09f190d24338d604cdecfef9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Nov 2025 13:56:46 -0800
+Subject: bnxt_en: Do not set EOP on RX AGG BDs on 5760X chips
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit 30f253f8d9a01d532fdb7ec6c8a9d4c15fe29241 ]
+
+With End-of-Packet padding (EOP) set, the chip will disable Relaxed
+Ordering (RO) of TPA data packets.  A TPA segment with EOP set will be
+padded to the next cache boundary and can potentially overwrite the
+beginning bytes of the next TPA segment when RO is enabled on 5760X.
+To prevent that, the chip disables RO for TPA when EOP is set.
+
+To take advantge of RO and higher performance, do not set EOP on
+5760X chips when TPA is enabled.  Define a proper RX_BD_FLAGS_AGG_EOP
+constant to make it clear that we are setting EOP.
+
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20251126215648.1885936-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: c3faf548a00f ("bnxt_en: Disable EOP for TPA on all chips to prevent data corruption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 ++++++++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index e9cc604834c51..f11ca14c5c4d3 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3764,7 +3764,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+       if ((bp->flags & BNXT_FLAG_AGG_RINGS)) {
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+-                      RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
++                      RX_BD_TYPE_RX_AGG_BD;
++
++              /* On P7, setting EOP will cause the chip to disable
++               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
++               * potentially higher performance with RO.
++               */
++              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++                      type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+       }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 2c12a5b34b11f..006987d3caa1a 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -103,6 +103,7 @@ struct rx_bd {
+        #define RX_BD_TYPE_48B_BD_SIZE                          (2 << 4)
+        #define RX_BD_TYPE_64B_BD_SIZE                          (3 << 4)
+       #define RX_BD_FLAGS_SOP                                 (1 << 6)
++      #define RX_BD_FLAGS_AGG_EOP                             (1 << 6)
+       #define RX_BD_FLAGS_EOP                                 (1 << 7)
+       #define RX_BD_FLAGS_BUFFERS                             (3 << 8)
+        #define RX_BD_FLAGS_1_BUFFER_PACKET                     (0 << 8)
+-- 
+2.53.0
+
diff --git a/queue-6.1/bnxt_en-fix-ptp-pps-setting-bug.patch b/queue-6.1/bnxt_en-fix-ptp-pps-setting-bug.patch
new file mode 100644 (file)
index 0000000..da6e83e
--- /dev/null
@@ -0,0 +1,54 @@
+From 45f6016d5b4edd8cb0df04a4ea3fdfc112b25860 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:37 -0700
+Subject: bnxt_en: Fix PTP PPS setting bug
+
+From: Keegan Freyhof <keegan.freyhof@broadcom.com>
+
+[ Upstream commit 80eaf88efec33ac77ed7726d066c4f2f932cc329 ]
+
+The existing driver logic is always turning on PTP_CLK_REQ_PPS
+regardless of the "on" parameter passed to bnxt_ptp_enable().
+During shutdown, PTP_CLK_REQ_PPS may be turned off and this
+bug will do the opposite and may trigger a PCIe PTM request TLP.
+On some systems this can trigger a PCIe AER.
+
+Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on"
+parameter.
+
+Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index 1c888d6c3aee8..850e4c44044ac 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -460,12 +460,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+               return rc;
+       case PTP_CLK_REQ_PPS:
+               /* Configure PHC PPS IN */
+-              rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
++              pin_id = 0;
++              if (!on)
++                      break;
++              rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+               if (rc)
+                       return rc;
+               rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
+               if (!rc)
+-                      ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
++                      ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL;
+               return rc;
+       default:
+               netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
+-- 
+2.53.0
+
diff --git a/queue-6.1/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-6.1/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..e970446
--- /dev/null
@@ -0,0 +1,80 @@
+From 67849cf8c52004548aaddff6ea7fa23cc2cb7889 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 9c4c2c7d90ef5..c44a9358f8b27 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1535,8 +1535,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1598,9 +1598,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-6.1/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..836fed3
--- /dev/null
@@ -0,0 +1,74 @@
+From 5906b8f9ad2b939d61abb276d5cb1eea1683ac50 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 4ff1d5007a23e..abb62b3e4f873 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -8491,11 +8491,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               break;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
+@@ -8563,7 +8564,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -9422,8 +9423,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch b/queue-6.1/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch
new file mode 100644 (file)
index 0000000..565a953
--- /dev/null
@@ -0,0 +1,240 @@
+From b816ecb15c6f02a446cc5cdecf61032140721a8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:09 -0700
+Subject: bpf: tcp: Avoid socket skips and repeats during iteration
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit f5080f612a1c587bf636bb23d2a2f4de276d60e4 ]
+
+Replace the offset-based approach for tracking progress through a bucket
+in the TCP table with one based on socket cookies. Remember the cookies
+of unprocessed sockets from the last batch and use this list to
+pick up where we left off or, in the case that the next socket
+disappears between reads, find the first socket after that point that
+still exists in the bucket and resume from there.
+
+This approach guarantees that all sockets that existed when iteration
+began and continue to exist throughout will be visited exactly once.
+Sockets that are added to the table during iteration may or may not be
+seen, but if they are they will be seen exactly once.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 147 ++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 115 insertions(+), 32 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 9843e05343565..8fcf9c990318b 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -58,6 +58,7 @@
+ #include <linux/times.h>
+ #include <linux/slab.h>
+ #include <linux/sched.h>
++#include <linux/sock_diag.h>
+ #include <net/net_namespace.h>
+ #include <net/icmp.h>
+@@ -2727,6 +2728,7 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ #ifdef CONFIG_BPF_SYSCALL
+ union bpf_tcp_iter_batch_item {
+       struct sock *sk;
++      __u64 cookie;
+ };
+ struct bpf_tcp_iter_state {
+@@ -2757,10 +2759,19 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
+ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ {
++      union bpf_tcp_iter_batch_item *item;
+       unsigned int cur_sk = iter->cur_sk;
++      __u64 cookie;
+-      while (cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[cur_sk++].sk);
++      /* Remember the cookies of the sockets we haven't seen yet, so we can
++       * pick up where we left off next time around.
++       */
++      while (cur_sk < iter->end_sk) {
++              item = &iter->batch[cur_sk++];
++              cookie = sock_gen_cookie(item->sk);
++              sock_gen_put(item->sk);
++              item->cookie = cookie;
++      }
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+@@ -2781,6 +2792,106 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+       return 0;
+ }
++static struct sock *bpf_iter_tcp_resume_bucket(struct sock *first_sk,
++                                             union bpf_tcp_iter_batch_item *cookies,
++                                             int n_cookies)
++{
++      struct hlist_nulls_node *node;
++      struct sock *sk;
++      int i;
++
++      for (i = 0; i < n_cookies; i++) {
++              sk = first_sk;
++              sk_nulls_for_each_from(sk, node)
++                      if (cookies[i].cookie == atomic64_read(&sk->sk_cookie))
++                              return sk;
++      }
++
++      return NULL;
++}
++
++static struct sock *bpf_iter_tcp_resume_listening(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      unsigned int find_cookie = iter->cur_sk;
++      unsigned int end_cookie = iter->end_sk;
++      int resume_bucket = st->bucket;
++      struct sock *sk;
++
++      if (end_cookie && find_cookie == end_cookie)
++              ++st->bucket;
++
++      sk = listening_get_first(seq);
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      if (sk && st->bucket == resume_bucket && end_cookie) {
++              sk = bpf_iter_tcp_resume_bucket(sk, &iter->batch[find_cookie],
++                                              end_cookie - find_cookie);
++              if (!sk) {
++                      spin_unlock(&hinfo->lhash2[st->bucket].lock);
++                      ++st->bucket;
++                      sk = listening_get_first(seq);
++              }
++      }
++
++      return sk;
++}
++
++static struct sock *bpf_iter_tcp_resume_established(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      unsigned int find_cookie = iter->cur_sk;
++      unsigned int end_cookie = iter->end_sk;
++      int resume_bucket = st->bucket;
++      struct sock *sk;
++
++      if (end_cookie && find_cookie == end_cookie)
++              ++st->bucket;
++
++      sk = established_get_first(seq);
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      if (sk && st->bucket == resume_bucket && end_cookie) {
++              sk = bpf_iter_tcp_resume_bucket(sk, &iter->batch[find_cookie],
++                                              end_cookie - find_cookie);
++              if (!sk) {
++                      spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
++                      ++st->bucket;
++                      sk = established_get_first(seq);
++              }
++      }
++
++      return sk;
++}
++
++static struct sock *bpf_iter_tcp_resume(struct seq_file *seq)
++{
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      struct sock *sk = NULL;
++
++      switch (st->state) {
++      case TCP_SEQ_STATE_LISTENING:
++              sk = bpf_iter_tcp_resume_listening(seq);
++              if (sk)
++                      break;
++              st->bucket = 0;
++              st->state = TCP_SEQ_STATE_ESTABLISHED;
++              fallthrough;
++      case TCP_SEQ_STATE_ESTABLISHED:
++              sk = bpf_iter_tcp_resume_established(seq);
++              break;
++      }
++
++      return sk;
++}
++
+ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+                                                struct sock **start_sk)
+ {
+@@ -2865,32 +2976,12 @@ static void bpf_iter_tcp_unlock_bucket(struct seq_file *seq)
+ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       unsigned int expected;
+       struct sock *sk;
+       int err;
+-      /* The st->bucket is done.  Directly advance to the next
+-       * bucket instead of having the tcp_seek_last_pos() to skip
+-       * one by one in the current bucket and eventually find out
+-       * it has to advance to the next bucket.
+-       */
+-      if (iter->end_sk && iter->cur_sk == iter->end_sk) {
+-              st->offset = 0;
+-              st->bucket++;
+-              if (st->state == TCP_SEQ_STATE_LISTENING &&
+-                  st->bucket > hinfo->lhash2_mask) {
+-                      st->state = TCP_SEQ_STATE_ESTABLISHED;
+-                      st->bucket = 0;
+-              }
+-      }
+-
+-      iter->cur_sk = 0;
+-      iter->end_sk = 0;
+-
+-      sk = tcp_seek_last_pos(seq);
++      sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+@@ -2906,10 +2997,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       if (err)
+               return ERR_PTR(err);
+-      iter->cur_sk = 0;
+-      iter->end_sk = 0;
+-
+-      sk = tcp_seek_last_pos(seq);
++      sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+@@ -2961,11 +3049,6 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+                * meta.seq_num is used instead.
+                */
+               st->num++;
+-              /* Move st->offset to the next sk in the bucket such that
+-               * the future start() will resume at st->offset in
+-               * st->bucket.  See tcp_seek_last_pos().
+-               */
+-              st->offset++;
+               sock_gen_put(iter->batch[iter->cur_sk++].sk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch b/queue-6.1/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
new file mode 100644 (file)
index 0000000..d8b60e9
--- /dev/null
@@ -0,0 +1,170 @@
+From f00b8e518ee706106c203941d9b6a2c5c7aefe7d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:32:47 +0000
+Subject: bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()
+
+From: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+
+[ Upstream commit e5fd3f514e27db1f05fbd72ba615d74941e23c51 ]
+
+reqsk_queue_hash_req() publishes a TCP_NEW_SYN_RECV request_sock onto
+the ehash chain, drops the bucket lock, and only afterwards sets
+rsk_refcnt to 3.
+
+Lockless readers such as __inet_lookup_established() handle this with
+refcount_inc_not_zero(), but bpf_iter_tcp_established_batch() uses plain
+sock_hold() while holding the bucket lock, on the assumption that the
+lock guarantees sk_refcnt > 0. That assumption does not hold for
+request_sock:
+
+  CPU 0                                CPU 1
+  -----                                -----
+  tcp_conn_request()
+   reqsk_queue_hash_req()
+    inet_ehash_insert(req)
+     spin_lock(bucket)
+     __sk_nulls_add_node_rcu(req)      // rsk_refcnt == 0
+     spin_unlock(bucket)
+                                       bpf_iter_tcp_established_batch()
+                                        spin_lock(bucket)
+                                        sock_hold(req)   <-- addition on 0
+                                        spin_unlock(bucket)
+    refcount_set(&req->rsk_refcnt, 3)  // clobbers saturated value
+
+which surfaces as:
+
+  refcount_t: addition on 0; use-after-free.
+  WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x48/0x90, CPU#1
+  Call Trace:
+   bpf_iter_tcp_established_batch+0x14e/0x170
+   bpf_iter_tcp_batch+0x53/0x200
+   bpf_iter_tcp_seq_next+0x27/0x70
+   bpf_seq_read+0x107/0x410
+   vfs_read+0xb9/0x380
+
+The iterator's stolen reference is lost when the publishing CPU's
+refcount_set() overwrites the count, leaving the socket one reference
+short. When the last legitimate owner drops its reference the reqsk is
+freed while still reachable, leading to use-after-free.
+
+This reproduces in seconds with tcp_syncookies=0, a handful of threads
+doing connect()/close() to a local listener while others read an
+iter/tcp link in a tight loop.
+
+Use refcount_inc_not_zero() and skip the socket on failure. A skipped
+socket is still part of the bucket, so keep counting it in expected.
+The reallocations are sized from expected, and a request sock whose
+refcount gets published while the lock is held across the last realloc
+must already have room.
+
+A skipped socket is counted in expected but never batched, so end_sk
+can be short of expected on a batch that is actually complete. Decide
+completeness by whether the walk left any socket behind instead. The
+WARN after the locked realloc checks the same, replacing an
+end_sk == expected check that could not hold on that path since
+commit cdec67a489d4 ("bpf: tcp: Make sure iter->batch always
+contains a full bucket snapshot").
+
+If every matching socket in a bucket is mid-init (refcount 0), end_sk
+stays 0. Advance to the next bucket rather than returning a batch entry
+that was never filled this round.
+
+Fixes: 04c7820b776f ("bpf: tcp: Bpf iter batching and lock_sock")
+Assisted-by: Claude:unspecified
+Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://lore.kernel.org/bpf/20260730-bpf-iter-tcp-refcnt-v3-1-754b9c8a6717@linux.dev
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 43 ++++++++++++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 19 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 8fcf9c990318b..25673067a5cda 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2926,24 +2926,24 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+ {
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct hlist_nulls_node *node;
+-      unsigned int expected = 1;
+-      struct sock *sk;
+-
+-      sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++].sk = *start_sk;
++      struct sock *sk = *start_sk;
++      unsigned int expected = 0;
+-      sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+-              if (seq_sk_match(seq, sk)) {
+-                      if (iter->end_sk < iter->max_sk) {
+-                              sock_hold(sk);
+-                              iter->batch[iter->end_sk++].sk = sk;
+-                      } else if (!*start_sk) {
+-                              /* Remember where we left off. */
+-                              *start_sk = sk;
+-                      }
+-                      expected++;
++              if (!seq_sk_match(seq, sk))
++                      continue;
++              expected++;
++              if (iter->end_sk < iter->max_sk) {
++                      /* reqsk_queue_hash_req() inserts with sk_refcnt == 0
++                       * and refcount_set()s it after the bucket lock drops.
++                       */
++                      if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
++                              continue;
++                      iter->batch[iter->end_sk++].sk = sk;
++              } else if (!*start_sk) {
++                      /* Remember where we left off. */
++                      *start_sk = sk;
+               }
+       }
+@@ -2981,12 +2981,13 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       struct sock *sk;
+       int err;
++again:
+       sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was too small. */
+@@ -3002,7 +3003,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was still too small. Hold onto the lock while we try
+@@ -3015,10 +3016,14 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return ERR_PTR(err);
+       }
+-      expected = bpf_iter_fill_batch(seq, &sk);
+-      WARN_ON_ONCE(iter->end_sk != expected);
++      bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(sk);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
++      if (unlikely(!iter->end_sk)) {
++              ++iter->state.bucket;
++              goto again;
++      }
+       return iter->batch[0].sk;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-tcp-get-rid-of-st_bucket_done.patch b/queue-6.1/bpf-tcp-get-rid-of-st_bucket_done.patch
new file mode 100644 (file)
index 0000000..35ab7cb
--- /dev/null
@@ -0,0 +1,82 @@
+From 152c092fa6ea7f2459644d30af6d57ac6f6e301f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:07 -0700
+Subject: bpf: tcp: Get rid of st_bucket_done
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit e25ab9b874a4bd8c6e3e5ce66cbe8a1dd4096e2e ]
+
+Get rid of the st_bucket_done field to simplify TCP iterator state and
+logic. Before, st_bucket_done could be false if bpf_iter_tcp_batch
+returned a partial batch; however, with the last patch ("bpf: tcp: Make
+sure iter->batch always contains a full bucket snapshot"),
+st_bucket_done == true is equivalent to iter->cur_sk == iter->end_sk.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 70c15160d2491..fb975e8f55ae5 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2731,7 +2731,6 @@ struct bpf_tcp_iter_state {
+       unsigned int end_sk;
+       unsigned int max_sk;
+       struct sock **batch;
+-      bool st_bucket_done;
+ };
+ struct bpf_iter__tcp {
+@@ -2754,8 +2753,10 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
+ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ {
+-      while (iter->cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[iter->cur_sk++]);
++      unsigned int cur_sk = iter->cur_sk;
++
++      while (cur_sk < iter->end_sk)
++              sock_gen_put(iter->batch[cur_sk++]);
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+@@ -2872,7 +2873,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+        * one by one in the current bucket and eventually find out
+        * it has to advance to the next bucket.
+        */
+-      if (iter->st_bucket_done) {
++      if (iter->end_sk && iter->cur_sk == iter->end_sk) {
+               st->offset = 0;
+               st->bucket++;
+               if (st->state == TCP_SEQ_STATE_LISTENING &&
+@@ -2884,7 +2885,6 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       iter->cur_sk = 0;
+       iter->end_sk = 0;
+-      iter->st_bucket_done = true;
+       sk = tcp_seek_last_pos(seq);
+       if (!sk)
+@@ -3032,10 +3032,8 @@ static void bpf_iter_tcp_seq_stop(struct seq_file *seq, void *v)
+                       (void)tcp_prog_seq_show(prog, &meta, v, 0);
+       }
+-      if (iter->cur_sk < iter->end_sk) {
++      if (iter->cur_sk < iter->end_sk)
+               bpf_iter_tcp_put_batch(iter);
+-              iter->st_bucket_done = false;
+-      }
+ }
+ static const struct seq_operations bpf_iter_tcp_seq_ops = {
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch b/queue-6.1/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch
new file mode 100644 (file)
index 0000000..edafe42
--- /dev/null
@@ -0,0 +1,64 @@
+From e55f46d6888c865fcfb440c07388157d9cc9f00e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:05 -0700
+Subject: bpf: tcp: Make mem flags configurable through
+ bpf_iter_tcp_realloc_batch
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit 8271bec9fc1cfe522b1a18cacbefd6712a3d41c2 ]
+
+Prepare for the next patch which needs to be able to choose either
+GFP_USER or GFP_NOWAIT for calls to bpf_iter_tcp_realloc_batch.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 89200b4314018..7823e55bc9e73 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2759,12 +2759,12 @@ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+-                                    unsigned int new_batch_sz)
++                                    unsigned int new_batch_sz, gfp_t flags)
+ {
+       struct sock **new_batch;
+       new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
+-                           GFP_USER | __GFP_NOWARN);
++                           flags | __GFP_NOWARN);
+       if (!new_batch)
+               return -ENOMEM;
+@@ -2876,7 +2876,8 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return sk;
+       }
+-      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2)) {
++      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
++                                                  GFP_USER)) {
+               resized = true;
+               goto again;
+       }
+@@ -3293,7 +3294,7 @@ static int bpf_iter_init_tcp(void *priv_data, struct bpf_iter_aux_info *aux)
+       if (err)
+               return err;
+-      err = bpf_iter_tcp_realloc_batch(iter, INIT_BATCH_SZ);
++      err = bpf_iter_tcp_realloc_batch(iter, INIT_BATCH_SZ, GFP_USER);
+       if (err) {
+               bpf_iter_fini_seq_net(priv_data);
+               return err;
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch b/queue-6.1/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch
new file mode 100644 (file)
index 0000000..4876a09
--- /dev/null
@@ -0,0 +1,257 @@
+From ee0fda8353af9fbcbb1f0d0daf786b19806e088d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:06 -0700
+Subject: bpf: tcp: Make sure iter->batch always contains a full bucket
+ snapshot
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit cdec67a489d4fdae3e83e04fca0419136a83c4c2 ]
+
+Require that iter->batch always contains a full bucket snapshot. This
+invariant is important to avoid skipping or repeating sockets during
+iteration when combined with the next few patches. Before, there were
+two cases where a call to bpf_iter_tcp_batch may only capture part of a
+bucket:
+
+1. When bpf_iter_tcp_realloc_batch() returns -ENOMEM.
+2. When more sockets are added to the bucket while calling
+   bpf_iter_tcp_realloc_batch(), making the updated batch size
+   insufficient.
+
+In cases where the batch size only covers part of a bucket, it is
+possible to forget which sockets were already visited, especially if we
+have to process a bucket in more than two batches. This forces us to
+choose between repeating or skipping sockets, so don't allow this:
+
+1. Stop iteration and propagate -ENOMEM up to userspace if reallocation
+   fails instead of continuing with a partial batch.
+2. Try bpf_iter_tcp_realloc_batch() with GFP_USER just as before, but if
+   we still aren't able to capture the full bucket, call
+   bpf_iter_tcp_realloc_batch() again while holding the bucket lock to
+   guarantee the bucket does not change. On the second attempt use
+   GFP_NOWAIT since we hold onto the spin lock.
+
+I did some manual testing to exercise the code paths where GFP_NOWAIT is
+used and where ERR_PTR(err) is returned. I used the realloc test cases
+included later in this series to trigger a scenario where a realloc
+happens inside bpf_iter_tcp_batch and made a small code tweak to force
+the first realloc attempt to allocate a too-small batch, thus requiring
+another attempt with GFP_NOWAIT. Some printks showed both reallocs with
+the tests passing:
+
+Jun 27 00:00:53 crow kernel: again GFP_USER
+Jun 27 00:00:53 crow kernel: again GFP_NOWAIT
+Jun 27 00:00:53 crow kernel: again GFP_USER
+Jun 27 00:00:53 crow kernel: again GFP_NOWAIT
+
+With this setup, I also forced each of the bpf_iter_tcp_realloc_batch
+calls to return -ENOMEM to ensure that iteration ends and that the
+read() in userspace fails.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 109 +++++++++++++++++++++++++++++++-------------
+ 1 file changed, 77 insertions(+), 32 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 7823e55bc9e73..70c15160d2491 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2768,7 +2768,7 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+       if (!new_batch)
+               return -ENOMEM;
+-      bpf_iter_tcp_put_batch(iter);
++      memcpy(new_batch, iter->batch, sizeof(*iter->batch) * iter->end_sk);
+       kvfree(iter->batch);
+       iter->batch = new_batch;
+       iter->max_sk = new_batch_sz;
+@@ -2777,69 +2777,95 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+ }
+ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+-                                               struct sock *start_sk)
++                                               struct sock **start_sk)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       struct hlist_nulls_node *node;
+       unsigned int expected = 1;
+       struct sock *sk;
+-      sock_hold(start_sk);
+-      iter->batch[iter->end_sk++] = start_sk;
++      sock_hold(*start_sk);
++      iter->batch[iter->end_sk++] = *start_sk;
+-      sk = sk_nulls_next(start_sk);
++      sk = sk_nulls_next(*start_sk);
++      *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+                               iter->batch[iter->end_sk++] = sk;
++                      } else if (!*start_sk) {
++                              /* Remember where we left off. */
++                              *start_sk = sk;
+                       }
+                       expected++;
+               }
+       }
+-      spin_unlock(&hinfo->lhash2[st->bucket].lock);
+       return expected;
+ }
+ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+-                                                 struct sock *start_sk)
++                                                 struct sock **start_sk)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       struct hlist_nulls_node *node;
+       unsigned int expected = 1;
+       struct sock *sk;
+-      sock_hold(start_sk);
+-      iter->batch[iter->end_sk++] = start_sk;
++      sock_hold(*start_sk);
++      iter->batch[iter->end_sk++] = *start_sk;
+-      sk = sk_nulls_next(start_sk);
++      sk = sk_nulls_next(*start_sk);
++      *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+                               iter->batch[iter->end_sk++] = sk;
++                      } else if (!*start_sk) {
++                              /* Remember where we left off. */
++                              *start_sk = sk;
+                       }
+                       expected++;
+               }
+       }
+-      spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
+       return expected;
+ }
++static unsigned int bpf_iter_fill_batch(struct seq_file *seq,
++                                      struct sock **start_sk)
++{
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++
++      if (st->state == TCP_SEQ_STATE_LISTENING)
++              return bpf_iter_tcp_listening_batch(seq, start_sk);
++      else
++              return bpf_iter_tcp_established_batch(seq, start_sk);
++}
++
++static void bpf_iter_tcp_unlock_bucket(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++
++      if (st->state == TCP_SEQ_STATE_LISTENING)
++              spin_unlock(&hinfo->lhash2[st->bucket].lock);
++      else
++              spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
++}
++
+ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+ {
+       struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct tcp_iter_state *st = &iter->state;
+       unsigned int expected;
+-      bool resized = false;
+       struct sock *sk;
++      int err;
+       /* The st->bucket is done.  Directly advance to the next
+        * bucket instead of having the tcp_seek_last_pos() to skip
+@@ -2856,33 +2882,52 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               }
+       }
+-again:
+-      /* Get a new batch */
+       iter->cur_sk = 0;
+       iter->end_sk = 0;
+-      iter->st_bucket_done = false;
++      iter->st_bucket_done = true;
+       sk = tcp_seek_last_pos(seq);
+       if (!sk)
+               return NULL; /* Done */
+-      if (st->state == TCP_SEQ_STATE_LISTENING)
+-              expected = bpf_iter_tcp_listening_batch(seq, sk);
+-      else
+-              expected = bpf_iter_tcp_established_batch(seq, sk);
++      expected = bpf_iter_fill_batch(seq, &sk);
++      if (likely(iter->end_sk == expected))
++              goto done;
+-      if (iter->end_sk == expected) {
+-              iter->st_bucket_done = true;
+-              return sk;
+-      }
++      /* Batch size was too small. */
++      bpf_iter_tcp_unlock_bucket(seq);
++      bpf_iter_tcp_put_batch(iter);
++      err = bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
++                                       GFP_USER);
++      if (err)
++              return ERR_PTR(err);
++
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      sk = tcp_seek_last_pos(seq);
++      if (!sk)
++              return NULL; /* Done */
++
++      expected = bpf_iter_fill_batch(seq, &sk);
++      if (likely(iter->end_sk == expected))
++              goto done;
+-      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
+-                                                  GFP_USER)) {
+-              resized = true;
+-              goto again;
++      /* Batch size was still too small. Hold onto the lock while we try
++       * again with a larger batch to make sure the current bucket's size
++       * does not change in the meantime.
++       */
++      err = bpf_iter_tcp_realloc_batch(iter, expected, GFP_NOWAIT);
++      if (err) {
++              bpf_iter_tcp_unlock_bucket(seq);
++              return ERR_PTR(err);
+       }
+-      return sk;
++      expected = bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(iter->end_sk != expected);
++done:
++      bpf_iter_tcp_unlock_bucket(seq);
++      return iter->batch[0];
+ }
+ static void *bpf_iter_tcp_seq_start(struct seq_file *seq, loff_t *pos)
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch b/queue-6.1/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch
new file mode 100644 (file)
index 0000000..c17d4ea
--- /dev/null
@@ -0,0 +1,124 @@
+From 0dc2b0f88c1c5f6e8a4bfa9e598623b7a967f7ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:08 -0700
+Subject: bpf: tcp: Use bpf_tcp_iter_batch_item for bpf_tcp_iter_state batch
+ items
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit efeb820951ebf3778830256496ff72d00d135310 ]
+
+Prepare for the next patch that tracks cookies between iterations by
+converting struct sock **batch to union bpf_tcp_iter_batch_item *batch
+inside struct bpf_tcp_iter_state.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index fb975e8f55ae5..9843e05343565 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2725,12 +2725,16 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ }
+ #ifdef CONFIG_BPF_SYSCALL
++union bpf_tcp_iter_batch_item {
++      struct sock *sk;
++};
++
+ struct bpf_tcp_iter_state {
+       struct tcp_iter_state state;
+       unsigned int cur_sk;
+       unsigned int end_sk;
+       unsigned int max_sk;
+-      struct sock **batch;
++      union bpf_tcp_iter_batch_item *batch;
+ };
+ struct bpf_iter__tcp {
+@@ -2756,13 +2760,13 @@ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+       unsigned int cur_sk = iter->cur_sk;
+       while (cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[cur_sk++]);
++              sock_gen_put(iter->batch[cur_sk++].sk);
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+                                     unsigned int new_batch_sz, gfp_t flags)
+ {
+-      struct sock **new_batch;
++      union bpf_tcp_iter_batch_item *new_batch;
+       new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
+                            flags | __GFP_NOWARN);
+@@ -2786,7 +2790,7 @@ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+       struct sock *sk;
+       sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++] = *start_sk;
++      iter->batch[iter->end_sk++].sk = *start_sk;
+       sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+@@ -2794,7 +2798,7 @@ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+-                              iter->batch[iter->end_sk++] = sk;
++                              iter->batch[iter->end_sk++].sk = sk;
+                       } else if (!*start_sk) {
+                               /* Remember where we left off. */
+                               *start_sk = sk;
+@@ -2815,7 +2819,7 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+       struct sock *sk;
+       sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++] = *start_sk;
++      iter->batch[iter->end_sk++].sk = *start_sk;
+       sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+@@ -2823,7 +2827,7 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+-                              iter->batch[iter->end_sk++] = sk;
++                              iter->batch[iter->end_sk++].sk = sk;
+                       } else if (!*start_sk) {
+                               /* Remember where we left off. */
+                               *start_sk = sk;
+@@ -2927,7 +2931,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       WARN_ON_ONCE(iter->end_sk != expected);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
+-      return iter->batch[0];
++      return iter->batch[0].sk;
+ }
+ static void *bpf_iter_tcp_seq_start(struct seq_file *seq, loff_t *pos)
+@@ -2962,11 +2966,11 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+                * st->bucket.  See tcp_seek_last_pos().
+                */
+               st->offset++;
+-              sock_gen_put(iter->batch[iter->cur_sk++]);
++              sock_gen_put(iter->batch[iter->cur_sk++].sk);
+       }
+       if (iter->cur_sk < iter->end_sk)
+-              sk = iter->batch[iter->cur_sk];
++              sk = iter->batch[iter->cur_sk].sk;
+       else
+               sk = bpf_iter_tcp_batch(seq);
+-- 
+2.53.0
+
diff --git a/queue-6.1/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch b/queue-6.1/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
new file mode 100644 (file)
index 0000000..c4db978
--- /dev/null
@@ -0,0 +1,96 @@
+From d777275b37f35293379d4d7c61d934a191182100 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 14:53:52 +0300
+Subject: btrfs: fix memory leak in btrfs_do_encoded_write()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit d2a4e4e626b2f4670b69b430c357f03f53eb6632 ]
+
+Local fuzzing of 6.12.94 has found the following memory leak:
+
+Unreferenced object 0xffff888018050a80 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 10 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
+    10 0a 05 18 80 88 ff ff 10 0a 05 18 80 88 ff ff  ................
+  backtrace (crc a8a6fc29):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    extent_changeset_alloc fs/btrfs/extent_io.h:207 [inline]
+    qgroup_reserve_data+0x1c5/0x7d0 fs/btrfs/qgroup.c:4305
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Unreferenced object 0xffff888018050a00 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 ff 0f 00 00 00 00 00 00  ................
+    90 0a 05 18 80 88 ff ff 90 0a 05 18 80 88 ff ff  ................
+  backtrace (crc cb5c9580):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    kzalloc_noprof include/linux/slab.h:1014 [inline]
+    ulist_prealloc+0x9c/0x110 fs/btrfs/ulist.c:114
+    extent_changeset_prealloc fs/btrfs/extent_io.h:217 [inline]
+    __set_extent_bit+0x16b/0x1a70 fs/btrfs/extent-io-tree.c:1086
+    set_record_extent_bits+0x50/0x90 fs/btrfs/extent-io-tree.c:1821
+    qgroup_reserve_data+0x274/0x7d0 fs/btrfs/qgroup.c:4312
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fix this by freeing an extent changeset before returning from
+btrfs_do_encoded_write().
+
+Fixes: 7c0c7269f7b5 ("btrfs: add BTRFS_IOC_ENCODED_WRITE")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 77b436bf1db76..b2a1d96a806a9 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -11181,6 +11181,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
+       }
+       kvfree(pages);
+ out:
++      extent_changeset_free(data_reserved);
+       if (ret >= 0)
+               iocb->ki_pos += encoded->len;
+       return ret;
+-- 
+2.53.0
+
diff --git a/queue-6.1/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-6.1/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..a02d626
--- /dev/null
@@ -0,0 +1,70 @@
+From da9005daa8f982289b2d8eb873fb5b6228f75e84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 2f631729a870b..f2cd7b599e44e 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -310,7 +310,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
+@@ -344,7 +344,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-6.1/hwmon-ads7828-fix-external-vref-regulator-handling.patch b/queue-6.1/hwmon-ads7828-fix-external-vref-regulator-handling.patch
new file mode 100644 (file)
index 0000000..0e976ca
--- /dev/null
@@ -0,0 +1,71 @@
+From c36c6d9465eae41f81a36337fd0c1f692196764b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 14:16:45 +0800
+Subject: hwmon: (ads7828) Fix external VREF regulator handling
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit fddb5ceaf901b050ed2a1a7deeecbf97e003435a ]
+
+The driver currently has two issues with the external VREF regulator
+handling in ads7828_probe():
+
+1. All errors from devm_regulator_get_optional() are ignored, causing the
+   driver to incorrectly fall back to internal VREF even for transient
+   errors like -EPROBE_DEFER or genuine failures like -ENOMEM.
+
+2. The external regulator is never enabled. The driver calls
+   regulator_get_voltage() without first calling regulator_enable(),
+   so the VREF pin may remain unpowered if the regulator is not
+   configured as always-on.
+
+Fix both issues by switching to devm_regulator_get_enable_read_voltage(),
+which handles regulator get, enable, and voltage read in one call.
+Only -ENODEV (no regulator specified in device tree) should trigger the
+fallback to internal VREF. All other errors are propagated to the caller.
+
+Fixes: a8ddfea09566 ("hwmon: (ads7828) Accept optional parameters from device tree")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260805061645.1331652-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ads7828.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
+index 7246198f09013..efd60b52e29b9 100644
+--- a/drivers/hwmon/ads7828.c
++++ b/drivers/hwmon/ads7828.c
+@@ -108,12 +108,11 @@ static int ads7828_probe(struct i2c_client *client)
+       struct ads7828_data *data;
+       struct device *hwmon_dev;
+       unsigned int vref_mv = ADS7828_INT_VREF_MV;
+-      unsigned int vref_uv;
++      int vref_uv;
+       bool diff_input = false;
+       bool ext_vref = false;
+       unsigned int regval;
+       enum ads7828_chips chip;
+-      struct regulator *reg;
+       data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
+       if (!data)
+@@ -127,9 +126,11 @@ static int ads7828_probe(struct i2c_client *client)
+       } else if (dev->of_node) {
+               diff_input = of_property_read_bool(dev->of_node,
+                                                  "ti,differential-input");
+-              reg = devm_regulator_get_optional(dev, "vref");
+-              if (!IS_ERR(reg)) {
+-                      vref_uv = regulator_get_voltage(reg);
++              vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref");
++              if (vref_uv < 0) {
++                      if (vref_uv != -ENODEV)
++                              return vref_uv;
++              } else {
+                       vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
+                       if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
+                           vref_mv > ADS7828_EXT_VREF_MV_MAX)
+-- 
+2.53.0
+
diff --git a/queue-6.1/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch b/queue-6.1/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
new file mode 100644 (file)
index 0000000..0e50645
--- /dev/null
@@ -0,0 +1,50 @@
+From 703d024563555b8974dc7f1be605e2ac58525ca9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 07:19:20 +0000
+Subject: hwmon: (corsair-psu) fix possible out-of-bounds access on missing
+ string termination
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit 36c4d73ce05d1d8896c2669eb0730d35a02a2ec1 ]
+
+In theory it could be possible that the REPLY_SIZE sized buffers for
+holding the vendor and product strings could be end up missing the null
+termination (for example by malicious hardware built on purpose)
+required by the seq_printf() call. That limits the debugfs printf calls
+to a maximum string length of REPLY_SIZE.
+
+Fixes: d115b51e0e567 ("hwmon: add Corsair PSU HID controller driver")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/anLj9gPWRoRDbQBV@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 2f2cbc067634a..8392a18758d21 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -647,7 +647,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->vendor);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
+       return 0;
+ }
+@@ -657,7 +657,7 @@ static int product_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->product);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/hwmon-lm25066-use-i2c_get_match_data.patch b/queue-6.1/hwmon-lm25066-use-i2c_get_match_data.patch
new file mode 100644 (file)
index 0000000..f8de8f3
--- /dev/null
@@ -0,0 +1,71 @@
+From fcd629107158eced94836794797bebd4e1ca0315 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Nov 2023 14:57:02 -0600
+Subject: hwmon: (lm25066) Use i2c_get_match_data()
+
+From: Rob Herring <robh@kernel.org>
+
+[ Upstream commit ac0c26bae662138eac9b49215e505b402f7e80e3 ]
+
+Use preferred i2c_get_match_data() instead of of_match_device() and
+i2c_match_id() to get the driver match data. With this, adjust the
+includes to explicitly include the correct headers.
+
+Adjust the 'chips' enum to not use 0, so that no match data can be
+distinguished from a valid enum value.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20231115205703.3730448-3-robh@kernel.org
+[groeck: Use double cast for enum chips assignment to make compiler happy]
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Stable-dep-of: 0dabe8a56f77 ("hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index 09792cd03d9fd..a99f073c2d0b9 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,10 +14,10 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
+-#include <linux/of_device.h>
++#include <linux/of.h>
+ #include "pmbus.h"
+-enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
++enum chips { lm25056 = 1, lm25066, lm5064, lm5066, lm5066i };
+ #define LM25066_READ_VAUX             0xd0
+ #define LM25066_MFR_READ_IIN          0xd1
+@@ -468,8 +468,6 @@ static int lm25066_probe(struct i2c_client *client)
+       struct lm25066_data *data;
+       struct pmbus_driver_info *info;
+       const struct __coeff *coeff;
+-      const struct of_device_id *of_id;
+-      const struct i2c_device_id *i2c_id;
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_READ_BYTE_DATA))
+@@ -484,14 +482,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (config < 0)
+               return config;
+-      i2c_id = i2c_match_id(lm25066_id, client);
++      data->id = (enum chips)(unsigned long)i2c_get_match_data(client);
+-      of_id = of_match_device(lm25066_of_match, &client->dev);
+-      if (of_id && (unsigned long)of_id->data != i2c_id->driver_data)
+-              dev_notice(&client->dev, "Device mismatch: %s in device tree, %s detected\n",
+-                         of_id->name, i2c_id->name);
+-
+-      data->id = i2c_id->driver_data;
+       info = &data->info;
+       info->pages = 1;
+-- 
+2.53.0
+
diff --git a/queue-6.1/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch b/queue-6.1/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
new file mode 100644 (file)
index 0000000..87bf549
--- /dev/null
@@ -0,0 +1,57 @@
+From 95713dd6d48c71f7a786121f5dfd07d24e6d3050 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:48:42 +0800
+Subject: hwmon: (nzxt-smart2) Check return value of init_device() in probe
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit d533882ce1060866a590257f2c77ee23eabef5b8 ]
+
+The init_device() call in nzxt_smart2_hid_probe() can fail because it
+sends HID output reports to the hardware to detect fans and set the
+update interval.  If the hardware is not responding or the HID reports
+fail, init_device() returns a negative error code.
+
+However, the return value was ignored, causing the probe to continue
+and register an hwmon device even though the device was never properly
+initialized.  This leads to an inconsistent state where the driver
+reports stale data or blocks on wait queues that will never be woken.
+
+The same function's return value is already checked in the
+reset_resume() handler, confirming the author's intent that errors
+should be propagated.
+
+Note that this fix was not possible before commit 59d104b54b0b
+("hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop")
+because the out_hw_close error path was missing hid_device_io_stop(),
+which would have opened a use-after-free risk window.
+
+Fixes: 53e68c20aeb1 ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2.")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260804074842.505923-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/nzxt-smart2.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
+index 90df6a7fc88d7..9f30ec0883fbc 100644
+--- a/drivers/hwmon/nzxt-smart2.c
++++ b/drivers/hwmon/nzxt-smart2.c
+@@ -754,7 +754,11 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
+       hid_device_io_start(hdev);
+-      init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      ret = init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      if (ret) {
++              dev_err(&hdev->dev, "init_device failed: %d\n", ret);
++              goto out_hw_close;
++      }
+       drvdata->hwmon =
+               hwmon_device_register_with_info(&hdev->dev, "nzxtsmart2", drvdata,
+-- 
+2.53.0
+
diff --git a/queue-6.1/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch b/queue-6.1/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
new file mode 100644 (file)
index 0000000..84c9972
--- /dev/null
@@ -0,0 +1,71 @@
+From 634f82a6d696eaad404d18bdf639a86bc982ced2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 14:12:31 -0700
+Subject: hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 0dabe8a56f772f0ece46d2597799f412c277d874 ]
+
+In lm25066_probe(), the PMBus coefficients for current and power are
+scaled based on the shunt resistor value. The calculation evaluates the
+multiplication using 32-bit arithmetic because info->m is an int and
+shunt is a u32:
+
+static int lm25066_probe(struct i2c_client *client) {
+    ...
+    info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+    info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
+    ...
+}
+
+For large coefficients like 26882 (LM25056) or 15076 (LM5066i), a device
+tree shunt-resistor-micro-ohms value exceeding approximately 159,000
+(159 mOhm, which is physically valid for low-current applications) causes
+the intermediate product to exceed UINT_MAX (4,294,967,295). This results
+in a silent wraparound before the division by 1000.
+
+Furthermore, if the wrapped value has the most significant bit set,
+converting it back to the signed int info->m results in negative
+coefficients. This logic error leads to drastically corrupted current and
+power readings, which can cause erratic thermal or power management
+behavior in the system.
+
+Fix the problem by using 64-bit operations for the multiply/divide
+operations. This can still overflow, but only for unreasonably large
+shunt resistor values.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: 94ee5fcc240fe ("hwmon: (pmbus/lm25066) Support configurable sense resistor values")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index a99f073c2d0b9..8fef24a25d728 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
++#include <linux/math.h>
+ #include <linux/of.h>
+ #include "pmbus.h"
+@@ -540,8 +541,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
+               shunt = 1000;
+-      info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+-      info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
++      info->m[PSC_CURRENT_IN] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_CURRENT_IN] * shunt, 1000);
++      info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_POWER] * shunt, 1000);
+ #if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)
+       /* LM25056 doesn't support OPERATION */
+-- 
+2.53.0
+
diff --git a/queue-6.1/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch b/queue-6.1/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
new file mode 100644 (file)
index 0000000..33110c7
--- /dev/null
@@ -0,0 +1,259 @@
+From 94832c514362b1ae3be0df45a070205b6cd78671 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:05 +0300
+Subject: ipvs: avoid out-of-bounds write in ip_vs_nat_icmp
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 646922a0379496154e8c8faca4f8e2fd9100cacc ]
+
+Sashiko warns that local attacker can modify the packet
+while it is processed by IPVS. Some places read the
+IP ihl field multiple times which can cause out-of-bounds
+access. One such place is ip_vs_nat_icmp where we
+can write after the validated area.
+
+Fix it by providing ciph argument just like it is done for
+IPv6 and use ciph->len as offset to the embedded transport
+header.
+
+Modify some IPv4 header checks by reading the ihl field
+only once.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://sashiko.dev/#/patchset/20260722101517.36313-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h             |  2 +-
+ net/netfilter/ipvs/ip_vs_core.c | 67 +++++++++++++++++----------------
+ net/netfilter/ipvs/ip_vs_xmit.c |  2 +-
+ 3 files changed, 36 insertions(+), 35 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 344f0082d3041..876852c2d37f5 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1577,7 +1577,7 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int dir, unsigned int toff,
+-                  bool has_ports);
++                  bool has_ports, struct ip_vs_iphdr *ciph);
+ #ifdef CONFIG_IP_VS_IPV6
+ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index 27c096b070774..7157ea5abaefa 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -747,28 +747,27 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
+  */
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int inout, unsigned int toff,
+-                  bool has_ports)
++                  bool has_ports, struct ip_vs_iphdr *ciph)
+ {
+       struct iphdr *iph        = ip_hdr(skb);
+       struct icmphdr *icmph    = (struct icmphdr *)(skb->data + toff);
+-      struct iphdr *ciph       = (struct iphdr *)(icmph + 1);
+-      unsigned int coff __maybe_unused = toff + sizeof(struct icmphdr);
++      struct iphdr *cih        = (struct iphdr *)(icmph + 1);
+       if (inout) {
+               iph->saddr = cp->vaddr.ip;
+               ip_send_check(iph);
+-              ciph->daddr = cp->vaddr.ip;
+-              ip_send_check(ciph);
++              cih->daddr = cp->vaddr.ip;
++              ip_send_check(cih);
+       } else {
+               iph->daddr = cp->daddr.ip;
+               ip_send_check(iph);
+-              ciph->saddr = cp->daddr.ip;
+-              ip_send_check(ciph);
++              cih->saddr = cp->daddr.ip;
++              ip_send_check(cih);
+       }
+       /* the TCP/UDP/SCTP port */
+       if (has_ports) {
+-              __be16 *ports = (void *)ciph + ciph->ihl*4;
++              __be16 *ports = (void *)(skb->data + ciph->len);
+               if (inout)
+                       ports[1] = cp->vport;
+@@ -782,10 +781,10 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       if (inout)
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered outgoing ICMP");
+       else
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered incoming ICMP");
+ }
+@@ -878,7 +877,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
+               ip_vs_nat_icmp_v6(skb, pp, cp, 1, toff, has_ports, ciph);
+       else
+ #endif
+-              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports);
++              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports, ciph);
+       if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
+               goto out;
+@@ -914,7 +913,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       struct ip_vs_iphdr ciph;
+       struct ip_vs_conn *cp;
+       struct ip_vs_protocol *pp;
+-      unsigned int offset, ihl;
++      unsigned int offset;
+       union nf_inet_addr snet;
+       *related = 1;
+@@ -927,7 +926,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+                       return NF_ACCEPT;
+       }
+-      ihl = ipvsh->len;
+       offset = ipvsh->len;
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
+@@ -953,11 +951,15 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      pp = ip_vs_proto_get(cih->protocol);
++      pp = ip_vs_proto_get(ciph.protocol);
+       if (!pp)
+               return NF_ACCEPT;
+@@ -968,8 +970,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking outgoing ICMP for");
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order */
+       cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
+                            ipvs, AF_INET, skb, &ciph);
+@@ -977,8 +977,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+               return NF_ACCEPT;
+       snet.ip = ipvsh->saddr.ip;
+-      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph, ihl,
+-                                  hooknum);
++      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph,
++                                  ipvsh->len, hooknum);
+ }
+ #ifdef CONFIG_IP_VS_IPV6
+@@ -1630,10 +1630,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!cih)
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      raddr = (union nf_inet_addr *)&cih->daddr;
+       hlen_ipip = cih->ihl * 4;
++      if (!(cih->version == 4 && hlen_ipip >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++      raddr = (union nf_inet_addr *)&cih->daddr;
+       /* Special case for errors for IPIP/UDP/GRE tunnel packets */
+       tunnel = false;
+@@ -1650,9 +1652,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+               if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP)
+                       return NF_ACCEPT;
+               offset += hlen_ipip;
+-              cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-              if (!(cih && cih->version == 4 && cih->ihl >= 5))
+-                      return NF_ACCEPT; /* The packet looks wrong, ignore */
+               tunnel = true;
+       } else if ((cih->protocol == IPPROTO_UDP ||     /* Can be UDP encap */
+                   cih->protocol == IPPROTO_GRE) &&    /* Can be GRE encap */
+@@ -1677,21 +1676,25 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+                       /* Skip IP and UDP/GRE tunnel headers */
+                       offset = offset2 + ulen;
+                       /* Now we should be at the original IP header */
+-                      cih = skb_header_pointer(skb, offset, sizeof(_ciph),
+-                                               &_ciph);
+-                      if (cih && cih->version == 4 && cih->ihl >= 5 &&
+-                          iproto == IPPROTO_IPIP)
++                      if (iproto == IPPROTO_IPIP)
+                               tunnel = true;
+                       else
+                               return NF_ACCEPT;
+               }
+       }
+-      pd = ip_vs_proto_data_get(ipvs, cih->protocol);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph))
++              return NF_ACCEPT;
++      pd = ip_vs_proto_data_get(ipvs, ciph.protocol);
+       if (!pd)
+               return NF_ACCEPT;
+       pp = pd->pp;
++      cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       /* Is the embedded protocol header present? */
+       if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
+               return NF_ACCEPT;
+@@ -1699,9 +1702,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking incoming ICMP for");
+-      offset2 = offset;
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order.
+        * For IPIP/UDP/GRE tunnel this is error for request, not for reply.
+        */
+@@ -1731,11 +1731,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       }
+       if (tunnel) {
+-              unsigned int hlen_orig = cih->ihl * 4;
++              unsigned int hlen_orig = ciph.len - ciph.off;
+               __be32 info = ic->un.gateway;
+               __u8 type = ic->type;
+               __u8 code = ic->code;
++              offset2 = offset;
+               /* Update the MTU */
+               if (ic->type == ICMP_DEST_UNREACH &&
+                   ic->code == ICMP_FRAG_NEEDED) {
+diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
+index db2f090e2f8f9..63dd0a3d251f8 100644
+--- a/net/netfilter/ipvs/ip_vs_xmit.c
++++ b/net/netfilter/ipvs/ip_vs_xmit.c
+@@ -1591,7 +1591,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+       if (skb_cow(skb, rt->dst.dev->hard_header_len))
+               goto tx_error;
+-      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports);
++      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports, ciph);
+       /* Another hack: avoid icmp_send in ip_fragment */
+       skb->ignore_df = 1;
+-- 
+2.53.0
+
diff --git a/queue-6.1/ipvs-return-the-csum-validation-for-forward-hook.patch b/queue-6.1/ipvs-return-the-csum-validation-for-forward-hook.patch
new file mode 100644 (file)
index 0000000..971685c
--- /dev/null
@@ -0,0 +1,100 @@
+From fac0aed665efce9a6b432cb8ee6e70d167de36ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:06 +0300
+Subject: ipvs: return the csum validation for forward hook
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 99609cb0aa789c8d071050ce8579989551882cc6 ]
+
+Sashiko notes that playing games with the skb dst and rt
+flags instead of providing hooknum is not a good idea
+when validating the checksums.
+
+Also, skipping checksum validation for FORWARD packets
+risk silent data corruption, even if the only user is
+the FTP-CMD packets coming from the real server.
+
+Sashiko also noticed that by using common checksum
+helper in the previous commit we actually fixed old bug
+where the TCP/UDP checksum for IPv6 on CHECKSUM_COMPLETE
+was not validated correctly.
+
+Fixes: e876b75b9020 ("ipvs: fix the checksum validations")
+Link: https://sashiko.dev/#/patchset/20260722211420.153933-1-pablo%40netfilter.org
+Link: https://sashiko.dev/#/patchset/20260727185024.67534-1-ja%40ssi.bg
+Link: https://sashiko.dev/#/patchset/20260728202520.59179-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h                   | 19 +++++--------------
+ net/netfilter/ipvs/ip_vs_proto_sctp.c |  2 +-
+ 2 files changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 876852c2d37f5..6df46a7a4f976 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -24,9 +24,7 @@
+ #include <linux/netfilter.h>          /* for union nf_inet_addr */
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>                       /* for struct ipv6hdr */
+-#include <net/route.h>
+ #include <net/ipv6.h>
+-#include <net/ip6_fib.h>
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ #include <net/netfilter/nf_conntrack.h>
+ #endif
+@@ -1610,30 +1608,23 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+       return csum_partial(diff, sizeof(diff), oldsum);
+ }
+-static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
++static inline bool ip_vs_checksum_needed(struct sk_buff *skb)
+ {
+       /* Checksum unnecessary or already validated? */
+       if (skb_csum_unnecessary(skb))
+               return false;
+-      /* LOCAL_OUT ? */
+-      if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
++      /* Locally generated ? */
++      if (!skb->dev)
+               return false;
+-      /* !LOCAL_IN (FORWARD) ? */
+-      if (af == AF_INET6) {
+-              if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
+-                      return false;
+-      } else {
+-              if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+-                      return false;
+-      }
+       return true;
+ }
+ static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
+                                              int offset, int proto, int af)
+ {
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return true;
++      /* Validate csum even for FORWARD */
+       return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+index 3dbd3096e1637..c80567c73469b 100644
+--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+@@ -193,7 +193,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+       struct sctphdr *sh;
+       __le32 cmp, val;
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return 1;
+       sh = (struct sctphdr *)(skb->data + sctphoff);
+       cmp = sh->checksum;
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch b/queue-6.1/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
new file mode 100644 (file)
index 0000000..59c2802
--- /dev/null
@@ -0,0 +1,81 @@
+From 6163896209d085306952514d3a56cca333ea87af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 13:15:08 +0000
+Subject: net/atm: fix slab-out-of-bounds read in vcc_setsockopt()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d0c80dbb970439bd2eeb0e5effff8c16a5f4e1e3 ]
+
+vcc_setsockopt() contained an ineffective optlen check:
+  if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+      return -EINVAL;
+
+If __SO_LEVEL_MATCH(optname, level) evaluated to false (e.g. if the caller
+passed a mismatched level), the length check optlen != __SO_SIZE(optname)
+was short-circuited and bypassed. Execution then fell through to switch(optname),
+calling copy_from_sockptr() assuming optval contained sufficient space.
+
+Furthermore, even if level matched, a cgroup BPF setsockopt filter could shrink
+optlen after entry. Because copy_from_sockptr() on kernel pointers uses memcpy(),
+this leads to a KASAN slab-out-of-bounds read when optlen is smaller than the
+expected structure size.
+
+Fix this by using copy_safe_from_sockptr(), which unconditionally validates
+that optlen is at least the expected size before copying. Also change the local
+'value' variable type from 'unsigned long' to 'int' so that SO_SETCLP matches
+its sizeof(int) ABI encoding on 64-bit systems.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+53ecc09fb81df10ef4de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=53ecc09fb81df10ef4de
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260805131508.3227331-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/atm/common.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/net/atm/common.c b/net/atm/common.c
+index 96f680a45e306..f3f68c231935a 100644
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+                  sockptr_t optval, unsigned int optlen)
+ {
+       struct atm_vcc *vcc;
+-      unsigned long value;
++      int value;
+       int error;
+       if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+@@ -772,8 +772,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+       {
+               struct atm_qos qos;
+-              if (copy_from_sockptr(&qos, optval, sizeof(qos)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&qos, sizeof(qos), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               error = check_qos(&qos);
+               if (error)
+                       return error;
+@@ -786,8 +788,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+               return 0;
+       }
+       case SO_SETCLP:
+-              if (copy_from_sockptr(&value, optval, sizeof(value)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&value, sizeof(value), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               if (value)
+                       vcc->atm_options |= ATM_ATMOPT_CLP;
+               else
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-6.1/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..e9b06f6
--- /dev/null
@@ -0,0 +1,42 @@
+From 682dc10f686b8843f13984b0392ce72d4f2ecc37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index f867e95311173..4834cf1cd9b3e 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1288,7 +1288,6 @@ static int hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-6.1/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..bed369f
--- /dev/null
@@ -0,0 +1,134 @@
+From 516393aa3719ededb21082b34e837e6d3e9b76dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 c216634c8919e..de0bb2669e4ce 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1036,13 +1036,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1082,7 +1080,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1093,7 +1091,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+@@ -1136,7 +1134,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Cleanup, is owner ? (%d)\n",
+@@ -1155,7 +1153,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1203,7 +1201,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-6.1/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..3c0c7da
--- /dev/null
@@ -0,0 +1,60 @@
+From b66009d5c7991c62e5c0131d9b6b8bc6e84c363c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index fe681680b5d91..a4ba1f6c9d228 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-6.1/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..1b6564d
--- /dev/null
@@ -0,0 +1,78 @@
+From f661bc67ecd3eeafe360f154de70faed4599e9cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 60ebc42a20e7e..3111817293aa0 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -890,8 +890,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -911,8 +909,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -927,6 +923,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-prestera-validate-firmware-header-length.patch b/queue-6.1/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..c8f78cc
--- /dev/null
@@ -0,0 +1,42 @@
+From d29ad82db7a015f25b85c8b616e0ba9db3a007c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index a37dbbda8de39..bc6af7b4909d9 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -673,6 +673,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-qrtr-ns-raise-lookup-limit-to-128.patch b/queue-6.1/net-qrtr-ns-raise-lookup-limit-to-128.patch
new file mode 100644 (file)
index 0000000..699d37c
--- /dev/null
@@ -0,0 +1,51 @@
+From 5a6fafeeaba1a57577cc0e4cc8dfeebbd936dbd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 22:18:30 +0200
+Subject: net: qrtr: ns: Raise lookup limit to 128
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Łukasz Patron <priv.luk@gmail.com>
+
+[ Upstream commit 7fc1c937b6b37c77df4ba374c37435ab06a2e945 ]
+
+Current limit of 64 is not enough for Sony Xperia 10 VII (SM6475).
+
+After merging v6.6.142 into a downstream AOSP device, it's stuck on
+boot animation and following log spam can be observed in dmesg:
+
+E qrtr    : ctrl_cmd_new_lookup(): QRTR client node exceeds max lookup limit!
+E qrtr    : qrtr_ns_worker(): failed while handling packet from 1:16600
+
+No idea why it needs more than 64 client lookups, but it appears to
+work fine with 128 as it did when there were no limits.
+
+I don't really have a good way to investigate what it needs all
+these lookups for as most of the userspace is closed source.
+
+Fixes: 5640227d9a21 ("net: qrtr: ns: Limit the maximum number of lookups")
+Signed-off-by: Łukasz Patron <priv.luk@gmail.com>
+Link: https://patch.msgid.link/20260804201919.1148015-1-priv.luk@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/qrtr/ns.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
+index 5220529a4c62d..4df5f0a9b7419 100644
+--- a/net/qrtr/ns.c
++++ b/net/qrtr/ns.c
+@@ -77,7 +77,7 @@ struct qrtr_node {
+  */
+ #define QRTR_NS_MAX_NODES   512
+ #define QRTR_NS_MAX_SERVERS 256
+-#define QRTR_NS_MAX_LOOKUPS 64
++#define QRTR_NS_MAX_LOOKUPS 128
+ static u16 node_count;
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-6.1/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..4984e1c
--- /dev/null
@@ -0,0 +1,45 @@
+From 5892613efbacc66ce4c0cfc3c20061a250920a47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 5f79f0b78321c..2a701e0b052b7 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -772,7 +772,6 @@ bool sk_mc_loop(struct sock *sk)
+               return inet6_sk(sk)->mc_loop;
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-6.1/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..108fe09
--- /dev/null
@@ -0,0 +1,142 @@
+From be9bc8cf78e82986787cd3d488a0e3ff2962688b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index 306188bf2d1ff..6c205fcb65475 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -51,6 +51,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -65,9 +66,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -80,9 +83,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -295,6 +300,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -305,6 +317,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -332,11 +349,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -551,7 +568,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-6.1/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..995aec8
--- /dev/null
@@ -0,0 +1,50 @@
+From 7968377f51e1c15ef1ef879abb10af5107cffa19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index e210a676dc340..1c6f2c623939f 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1281,7 +1281,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ntohs(ipv6h_check->payload_len);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-6.1/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..f6f67ee
--- /dev/null
@@ -0,0 +1,57 @@
+From 56572156102cd788fca51de6d955e3a01526b988 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index fcb24a0ccf761..761515b590f20 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1901,7 +1901,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch b/queue-6.1/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
new file mode 100644 (file)
index 0000000..6de9666
--- /dev/null
@@ -0,0 +1,71 @@
+From 2684d3671434507c511aa4a421f18f8aafdb657b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 09:07:01 +0200
+Subject: net/smc: fix TOCTOU race between smc_listen_out() and listener close
+
+From: Sidraya Jayagond <sidraya@linux.ibm.com>
+
+[ Upstream commit 185a4caeecabc150106deda1da170b09f2ad803f ]
+
+smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
+then acquires lock_sock_nested() only after the check passes. This
+opens a window where smc_close_active() can transition the listener
+to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
+queue, and release the lock, all between the lockless read and the
+delayed lock acquisition:
+
+  smc_listen_work (smc_hs_wq)          smc_close_active()
+  -------------------------------      -------------------------
+  release_sock(child)
+  if (sk_state == SMC_LISTEN) TRUE
+                                        lock_sock(listener)
+                                        sk_state = SMC_CLOSED
+                                        smc_close_cleanup_listen()
+                                        release_sock(listener)
+                                        flush_work(tcp_listen_work)
+  lock_sock_nested(listener)
+  smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
+
+smc_close_active() flushes only tcp_listen_work. Work items already
+dispatched onto smc_hs_wq for the CLC handshake continue running
+unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
+is never released, so the child smc_sock, its clcsock, and the
+reference all leak. A remote peer that opens TCP connections while the
+server calls close() can exhaust kernel memory.
+
+Move lock_sock_nested() to before the sk_state check so that the test
+and the enqueue are atomic under the listener lock.
+
+Fixes: fd57770dd198 ("net/smc: wait for pending work before clcsock release_sock")
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260803070701.126339-1-sidraya@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index ae97f47f4fda0..d069e5b156e51 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1874,11 +1874,12 @@ static void smc_listen_out(struct smc_sock *new_smc)
+               atomic_dec(&lsmc->queued_smc_hs);
+       release_sock(newsmcsk); /* lock in smc_listen_work() */
++      lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+       if (lsmc->sk.sk_state == SMC_LISTEN) {
+-              lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+               smc_accept_enqueue(&lsmc->sk, newsmcsk);
+               release_sock(&lsmc->sk);
+       } else { /* no longer listening */
++              release_sock(&lsmc->sk);
+               smc_close_non_accepted(newsmcsk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch b/queue-6.1/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
new file mode 100644 (file)
index 0000000..ade0d3d
--- /dev/null
@@ -0,0 +1,117 @@
+From fc31608ca42507671304f132c77a0d941e95556d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:38:50 +0000
+Subject: net: thunderbolt: Tear down DMA paths before stopping the rings
+
+From: Fan XinRan <shinjiangjiang@gmail.com>
+
+[ Upstream commit 68bf02b6b4ad3f748c6db71fd77b6c0402d252f4 ]
+
+tbnet_tear_down() stops both rings and frees their frame buffers before
+calling tb_xdomain_disable_paths().  tb_ring_stop() zeroes the ring's
+descriptor base and tbnet_free_buffers() unmaps and frees the pages the
+frames sit in, so by the time __tb_path_deactivate_hop() polls the hop's
+'pending' bit, anything still in flight has nowhere to drain to.
+
+The teardown sequence has been in this order since the driver was added.
+The setup path has not: commit ff7cd07f3064 ("net: thunderbolt: Enable
+DMA paths only after rings are enabled") moved the path enable to the end
+of tbnet_connected_work() and documented why:
+
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
+        */
+
+Teardown was never updated to match, so the rings and the paths now come
+down in the same order they go up instead of in reverse.
+
+On an ASMedia ASM4242 host router the 'pending' bit then never clears:
+every teardown burns the full 500 ms timeout and
+__tb_path_deactivate_hop() returns -ETIMEDOUT.  Raising the timeout to
+5 s does not help, so the hop is not slow to drain, it never drains
+at all.
+
+The failure is invisible above the thunderbolt core.
+__tb_path_deactivate_hops() is void and only calls tb_port_warn();
+tb_path_deactivate(), tb_tunnel_deactivate() and
+__tb_disconnect_xdomain_paths() are void as well, and
+tb_disconnect_xdomain_paths() ends in an unconditional "return 0".  So
+tb_xdomain_disable_paths() reports success and the netdev_warn() below
+it never fires.  Repeated teardowns eventually take the XDomain control
+channel down, after which the peer node is gone and only a power cycle
+brings the controller back.
+
+Deactivating the paths first fixes it.  Measured with kretprobes on a
+stock v6.17 tree with no other patches applied, on a link that was up
+and had just carried traffic:
+
+  before: __tb_path_deactivate_hop() returns 0 for the first hop, then
+          -ETIMEDOUT for the second 500335 us later
+  after:  0 for both, 525 us apart
+
+Alternating the two orderings ABBA over three load levels, four
+teardowns per arm: every teardown failed before the change (21 of 21
+that ran), none failed after (0 of 24).  The before arms ran short
+because the link died partway through.  The same split shows up when
+the interface is enslaved to a bond instead of just brought down, which
+is how I ran into this in the first place.  Throughput and latency after
+the change are unchanged.
+
+Hosts whose routers drain the hop despite the stale descriptor base see
+no functional difference, since the paths end up deactivated either way.
+
+Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
+Signed-off-by: Fan XinRan <shinjiangjiang@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260803-b4-tbnet-teardown-v2-1-27de6a13ca2d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
+index 6f01089e6f47d..a14655b795cca 100644
+--- a/drivers/net/thunderbolt.c
++++ b/drivers/net/thunderbolt.c
+@@ -379,11 +379,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+                               break;
+               }
+-              tb_ring_stop(net->rx_ring.ring);
+-              tb_ring_stop(net->tx_ring.ring);
+-              tbnet_free_buffers(&net->rx_ring);
+-              tbnet_free_buffers(&net->tx_ring);
+-
++              /* Tear the paths down before stopping the rings.  This mirrors
++               * tbnet_connected_work(), which enables the paths last so the
++               * Rx ring is primed before packets can arrive.  Stopping a
++               * ring zeroes its descriptor base and tbnet_free_buffers()
++               * unmaps and frees the frame buffers, leaving anything still
++               * in flight with nowhere to drain to;
++               * __tb_path_deactivate_hop() then waits for the hop's
++               * 'pending' bit, which on some host routers never clears in
++               * that state.
++               */
+               ret = tb_xdomain_disable_paths(net->xd,
+                                              net->local_transmit_path,
+                                              net->tx_ring.ring->hop,
+@@ -392,6 +397,11 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+               if (ret)
+                       netdev_warn(net->dev, "failed to disable DMA paths\n");
++              tb_ring_stop(net->rx_ring.ring);
++              tb_ring_stop(net->tx_ring.ring);
++              tbnet_free_buffers(&net->rx_ring);
++              tbnet_free_buffers(&net->tx_ring);
++
+               tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+               net->remote_transmit_path = 0;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-ipset-switch-ext_size-to-atomic64_t.patch b/queue-6.1/netfilter-ipset-switch-ext_size-to-atomic64_t.patch
new file mode 100644 (file)
index 0000000..25cded1
--- /dev/null
@@ -0,0 +1,134 @@
+From b2476013c836f66a0a3414150d4c9c6c6723724d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 20:38:50 +0200
+Subject: netfilter: ipset: switch ext_size to atomic64_t
+
+From: Jozsef Kadlecsik <kadlec@netfilter.org>
+
+[ Upstream commit 712a6f545c359b427daa9a5a782e30d2f8331e25 ]
+
+The hash types do not acquire set->lock, they use 'region locking' where
+only part of the hash table is locked. Parallel inserts and deletes are
+possible and CPUs can race on ->ext_size update.  Switch to atomic64_t.
+
+This leaves another bug unresolved: there still can be a race on
+comment extension re-init.  This will be handled in a later commit
+when converting to rhashtable backend.
+
+Fixes: f66ee0410b1c ("netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports")
+Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netfilter/ipset/ip_set.h  | 2 +-
+ net/netfilter/ipset/ip_set_bitmap_gen.h | 4 ++--
+ net/netfilter/ipset/ip_set_core.c       | 6 +++---
+ net/netfilter/ipset/ip_set_hash_gen.h   | 2 +-
+ net/netfilter/ipset/ip_set_list_set.c   | 4 ++--
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
+index d82413e6098a7..b2ee80b4b0d39 100644
+--- a/include/linux/netfilter/ipset/ip_set.h
++++ b/include/linux/netfilter/ipset/ip_set.h
+@@ -273,7 +273,7 @@ struct ip_set {
+       /* Number of elements (vs timeout) */
+       u32 elements;
+       /* Size of the dynamic extensions (vs timeout) */
+-      size_t ext_size;
++      atomic64_t ext_size;
+       /* Element data size */
+       size_t dsize;
+       /* Offsets to extensions in elements */
+diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
+index 9523104a90da4..40f0383883f9d 100644
+--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
++++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
+@@ -75,7 +75,7 @@ mtype_flush(struct ip_set *set)
+               mtype_ext_cleanup(set);
+       bitmap_zero(map->members, map->elements);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ /* Calculate the actual memory size of the set data */
+@@ -91,7 +91,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct mtype *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = mtype_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index 1d6579358f9ba..7601e4ca02775 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -350,7 +350,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       size_t len = ext->comment ? strlen(ext->comment) : 0;
+       if (unlikely(c)) {
+-              set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++              atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+               rcu_assign_pointer(comment->c, NULL);
+               kfree_rcu(c, rcu);
+       }
+@@ -362,7 +362,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       if (unlikely(!c))
+               return;
+       strscpy(c->str, ext->comment, len + 1);
+-      set->ext_size += sizeof(*c) + strlen(c->str) + 1;
++      atomic64_add(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, c);
+ }
+ EXPORT_SYMBOL_GPL(ip_set_init_comment);
+@@ -392,7 +392,7 @@ ip_set_comment_free(struct ip_set *set, void *ptr)
+       c = rcu_dereference_protected(comment->c, 1);
+       if (unlikely(!c))
+               return;
+-      set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++      atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, NULL);
+       kfree_rcu(c, rcu);
+ }
+diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
+index de9f291ff8c28..6588571648ead 100644
+--- a/net/netfilter/ipset/ip_set_hash_gen.h
++++ b/net/netfilter/ipset/ip_set_hash_gen.h
+@@ -1276,7 +1276,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+-      memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
++      memsize = mtype_ahash_memsize(h, t) + ext_size + atomic64_read(&set->ext_size);
+       htable_bits = t->htable_bits;
+       rcu_read_unlock_bh();
+diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
+index 7d1ba6ad514f5..bc37bc59e2828 100644
+--- a/net/netfilter/ipset/ip_set_list_set.c
++++ b/net/netfilter/ipset/ip_set_list_set.c
+@@ -421,7 +421,7 @@ list_set_flush(struct ip_set *set)
+       list_for_each_entry_safe(e, n, &map->members, list)
+               list_set_del(set, e);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ static void
+@@ -455,7 +455,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct list_set *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = list_set_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = list_set_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+-- 
+2.53.0
+
diff --git a/queue-6.1/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-6.1/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..b19e0e0
--- /dev/null
@@ -0,0 +1,50 @@
+From a637182c814db7b4aa588fbed7ce9f7139d49aa9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 8258bce82e5bc..9f352f1a6eb1e 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10388,6 +10388,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10429,6 +10430,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-6.1/regulator-devres-add-api-for-reference-voltage-suppl.patch b/queue-6.1/regulator-devres-add-api-for-reference-voltage-suppl.patch
new file mode 100644 (file)
index 0000000..74b8b63
--- /dev/null
@@ -0,0 +1,135 @@
+From 3e6e6c7428efd2361b315e4d25ab7d9f46999d75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 18:40:09 -0500
+Subject: regulator: devres: add API for reference voltage supplies
+
+From: David Lechner <dlechner@baylibre.com>
+
+[ Upstream commit b250c20b64290808aa4b5cc6d68819a7ee28237f ]
+
+A common use case for regulators is to supply a reference voltage to an
+analog input or output device. This adds a new devres API to get,
+enable, and get the voltage in a single call. This allows eliminating
+boilerplate code in drivers that use reference supplies in this way.
+
+Signed-off-by: David Lechner <dlechner@baylibre.com>
+Link: https://lore.kernel.org/r/20240429-regulator-get-enable-get-votlage-v2-1-b1f11ab766c1@baylibre.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: fddb5ceaf901 ("hwmon: (ads7828) Fix external VREF regulator handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../driver-api/driver-model/devres.rst        |  1 +
+ drivers/regulator/devres.c                    | 59 +++++++++++++++++++
+ include/linux/regulator/consumer.h            |  7 +++
+ 3 files changed, 67 insertions(+)
+
+diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
+index 56082265e8e50..11234c12718d1 100644
+--- a/Documentation/driver-api/driver-model/devres.rst
++++ b/Documentation/driver-api/driver-model/devres.rst
+@@ -413,6 +413,7 @@ REGULATOR
+   devm_regulator_bulk_put()
+   devm_regulator_get()
+   devm_regulator_get_enable()
++  devm_regulator_get_enable_read_voltage()
+   devm_regulator_get_enable_optional()
+   devm_regulator_get_exclusive()
+   devm_regulator_get_optional()
+diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
+index 5c7ff9b3e8a79..6e8d6dc729cef 100644
+--- a/drivers/regulator/devres.c
++++ b/drivers/regulator/devres.c
+@@ -145,6 +145,65 @@ struct regulator *devm_regulator_get_optional(struct device *dev,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
++/**
++ * devm_regulator_get_enable_read_voltage - Resource managed regulator get and
++ *                                          enable that returns the voltage
++ * @dev: device to supply
++ * @id:  supply name or regulator ID.
++ *
++ * Get and enable regulator for duration of the device life-time.
++ * regulator_disable() and regulator_put() are automatically called on driver
++ * detach. See regulator_get_optional(), regulator_enable(), and
++ * regulator_get_voltage() for more information.
++ *
++ * This is a convenience function for supplies that provide a reference voltage
++ * where the consumer driver just needs to know the voltage and keep the
++ * regulator enabled.
++ *
++ * In cases where the supply is not strictly required, callers can check for
++ * -ENODEV error and handle it accordingly.
++ *
++ * Returns: voltage in microvolts on success, or an error code on failure.
++ */
++int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id)
++{
++      struct regulator *r;
++      int ret;
++
++      /*
++       * Since we need a real voltage, we use devm_regulator_get_optional()
++       * rather than getting a dummy regulator with devm_regulator_get() and
++       * then letting regulator_get_voltage() fail with -EINVAL. This way, the
++       * caller can handle the -ENODEV error code if needed instead of the
++       * ambiguous -EINVAL.
++       */
++      r = devm_regulator_get_optional(dev, id);
++      if (IS_ERR(r))
++              return PTR_ERR(r);
++
++      ret = regulator_enable(r);
++      if (ret)
++              goto err_regulator_put;
++
++      ret = devm_add_action_or_reset(dev, regulator_action_disable, r);
++      if (ret)
++              goto err_regulator_put;
++
++      ret = regulator_get_voltage(r);
++      if (ret < 0)
++              goto err_release_action;
++
++      return 0;
++
++err_release_action:
++      devm_release_action(dev, regulator_action_disable, r);
++err_regulator_put:
++      devm_regulator_put(r);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(devm_regulator_get_enable_read_voltage);
++
+ static int devm_regulator_match(struct device *dev, void *res, void *data)
+ {
+       struct regulator **r = res;
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index 60bc7e143869b..8d3afff87b6e3 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -209,6 +209,7 @@ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
+                                                          const char *id);
+ int devm_regulator_get_enable(struct device *dev, const char *id);
+ int devm_regulator_get_enable_optional(struct device *dev, const char *id);
++int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id);
+ void regulator_put(struct regulator *regulator);
+ void devm_regulator_put(struct regulator *regulator);
+@@ -372,6 +373,12 @@ static inline int devm_regulator_get_enable_optional(struct device *dev,
+       return 0;
+ }
++static inline int devm_regulator_get_enable_read_voltage(struct device *dev,
++                                                       const char *id)
++{
++      return -ENODEV;
++}
++
+ static inline struct regulator *__must_check
+ regulator_get_optional(struct device *dev, const char *id)
+ {
+-- 
+2.53.0
+
diff --git a/queue-6.1/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch b/queue-6.1/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
new file mode 100644 (file)
index 0000000..fa8294e
--- /dev/null
@@ -0,0 +1,104 @@
+From b027f0b01039c63870bf12cd123f200908a3738e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 12:29:48 +0000
+Subject: Revert "net: thunderbolt: Enable end-to-end flow control also in
+ transmit"
+
+From: Fan Ye <fy15309206903@gmail.com>
+
+[ Upstream commit 1881f2efbf7f78dc0a79a387b29fde6ff56d3731 ]
+
+This reverts commit a8065af3346ebd7c76ebc113451fb3ba94cf7769.
+
+Per the USB4 spec, a Transmit Descriptor Ring with E2E flow control
+disabled does not require any credits to be available before the Host
+Interface Adapter Layer transmits a tunneled packet from it. Once E2E is
+enabled on that ring the controller must first obtain end-to-end
+credits.
+
+The ASMedia ASM4242 USB4 host router (PCI 1b21:2425) never delivers
+those credits. The controller does accept the configuration: reading the
+ring OPTIONS register back right after tb_ring_start() returns exactly
+what was written, including RING_FLAG_E2E_FLOW_CONTROL (bit 28) and the
+E2E HopID field. No credit ever arrives though, so the Tx ring's
+hardware consumer index never advances and the link carries no traffic
+at all.
+
+Measured on two hosts connected point to point, onboard ASM4242 on MSI
+X870E and X870, v6.17, stock drivers/net/thunderbolt/main.c with only
+this revert applied on top:
+
+  before: 100% packet loss to the peer; thunderbolt0 is up and the
+          XDomain handshake completes ("new host found"), but iperf3
+          fails with "No route to host" once the neighbour entry
+          expires
+  after:  0% packet loss, 0.28 ms RTT; iperf3 4.21 Gb/s one way and
+          5.17 Gb/s the other (5 runs each, stddev <= 0.02), 1
+          retransmit in 10 s
+
+An instrumented build additionally showed a frozen-Tx-consumer watchdog
+firing ~30k times in a 10 s window before this change.
+
+Rx-side E2E is not touched by this revert, so peers that do return
+credits keep receive-side flow control.
+
+ASMedia does not look like an isolated case. The out-of-tree
+thunderbolt-ibverbs project disables native E2E on AMD NHI by default,
+noting that "Strix Halo has reproduced TX completion wedges with
+multiple native E2E rings active" -- the same failure mode, on a
+different vendor. Since the driver has no way to tell in advance which
+host router returns the credits, going back to the previous behaviour
+looks safer than adding a quirk per affected part; Tx-side E2E can be
+reintroduced as an opt-in for controllers that are known to implement
+the credit return.
+
+Note that the reverted commit was not fixing a reported problem, it was
+derived from the spec wording alone, so this revert is not expected to
+regress a known workload. Cc'ing the original author in case there was
+one.
+
+Fixes: a8065af3346e ("net: thunderbolt: Enable end-to-end flow control also in transmit")
+Cc: zhangjianrong <zhangjianrong5@huawei.com>
+Signed-off-by: Fan Ye <fy15309206903@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260727123002.25225-1-fy15309206903@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
+index ef13aa36e55e8..6f01089e6f47d 100644
+--- a/drivers/net/thunderbolt.c
++++ b/drivers/net/thunderbolt.c
+@@ -884,12 +884,8 @@ static int tbnet_open(struct net_device *dev)
+       netif_carrier_off(dev);
+-      flags = RING_FLAG_FRAME;
+-      /* Only enable full E2E if the other end supports it too */
+-      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
+-              flags |= RING_FLAG_E2E;
+-
+-      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags);
++      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE,
++                              RING_FLAG_FRAME);
+       if (!ring) {
+               netdev_err(dev, "failed to allocate Tx ring\n");
+               return -ENOMEM;
+@@ -908,6 +904,11 @@ static int tbnet_open(struct net_device *dev)
+       sof_mask = BIT(TBIP_PDF_FRAME_START);
+       eof_mask = BIT(TBIP_PDF_FRAME_END);
++      flags = RING_FLAG_FRAME;
++      /* Only enable full E2E if the other end supports it too */
++      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
++              flags |= RING_FLAG_E2E;
++
+       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags,
+                               net->tx_ring.ring->hop, sof_mask,
+                               eof_mask, tbnet_start_poll, net);
+-- 
+2.53.0
+
diff --git a/queue-6.1/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-6.1/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..f296968
--- /dev/null
@@ -0,0 +1,54 @@
+From 879e9ab6a6e3aff68f8f71bf31158ef05ca48427 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 4dd36c8375507..4a79e855c85cd 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -575,6 +575,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-6.1/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-6.1/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..98e2668
--- /dev/null
@@ -0,0 +1,57 @@
+From 65c7b65748a0675ca35dad92c4acd80bebd5063e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 837fb8280bfd5..6d738f95aff1d 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3362,12 +3362,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-6.1/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch b/queue-6.1/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
new file mode 100644 (file)
index 0000000..50aaa5d
--- /dev/null
@@ -0,0 +1,88 @@
+From 75fc146554b94371e37cac9821244db25bd37c27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 21:46:35 +0200
+Subject: selftests/ftrace: refactor eprobes test to fix argument checks
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+[ Upstream commit 6e3abef2a27e7402a94111c9eff85d887e64a309 ]
+
+The add/remove eprobe test installs an eprobe for the openat syscall and
+runs ls. It checks the filenames that were opened by ls against a
+whitelist and a blacklist.
+
+Commit 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING
+pointer") fixed access to some string fields in eprobes. This triggers
+test failures as the blacklist does not allow relative paths for the
+openat parameters.
+
+What makes this test unstable is the fact that the openat calls vary a
+lot between different systems.
+
+Refactor the test to make it more robust. "cd <directory>" will issue a
+chdir syscall with the target directory as parameter. Set an eprobe on
+the sys_enter_chdir event and filter for the exact directory name. Allow
+(fault) as fallback.
+
+Link: https://lore.kernel.org/all/20260804194705.760893-1-martin@kaiser.cx/
+
+Fixes: 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING pointer")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202607151010.b68428e1-lkp@intel.com
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc  | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index c300eb0202620..e2322693d0c32 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,16 +1,16 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+ clear_dynamic_events
+ SYSTEM="syscalls"
+-EVENT="sys_enter_openat"
++EVENT="sys_enter_chdir"
+ FIELD="filename"
+-EPROBE="eprobe_open"
++EPROBE="eprobe_chdir"
+ OPTIONS="file=+0(\$filename):ustring"
+ echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+@@ -18,20 +18,14 @@ grep -q "$EPROBE" dynamic_events
+ test -d events/eprobes/$EPROBE
+ echo 1 > events/eprobes/$EPROBE/enable
+-ls
++cd /sys/kernel/tracing
+ echo 0 > events/eprobes/$EPROBE/enable
+-content=`grep '^ *ls-' trace | grep 'file='`
+-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
+-
++content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
+ if [ -z "$content" ]; then
+       exit_fail
+ fi
+-if [ ! -z "$nocontent" ]; then
+-      exit_fail
+-fi
+-
+ echo "-:$EPROBE" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+-- 
+2.53.0
+
index 437503364c0bbd56b719a5cd7de8ee1a11768cdd..d76905fd834e0991a469478447670545f1b4894a 100644 (file)
@@ -485,3 +485,50 @@ bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch
 bluetooth-hci_conn-fix-potential-uaf-in-create_big_s.patch
 mount-honour-sb_nouser-in-the-new-mount-api.patch
 s390-zcrypt-fix-missing-mem-scrub-at-clear-key-impor.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+netfilter-ipset-switch-ext_size-to-atomic64_t.patch
+ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
+ipvs-return-the-csum-validation-for-forward-hook.patch
+btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+tcp-add-a-scheduling-point-in-established_get_first.patch
+bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch
+bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch
+bpf-tcp-get-rid-of-st_bucket_done.patch
+bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch
+bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch
+bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
+vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
+hwmon-lm25066-use-i2c_get_match_data.patch
+hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
+selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
+bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
+bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
+bnxt_en-fix-ptp-pps-setting-bug.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
+net-qrtr-ns-raise-lookup-limit-to-128.patch
+net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
+hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
+regulator-devres-add-api-for-reference-voltage-suppl.patch
+hwmon-ads7828-fix-external-vref-regulator-handling.patch
diff --git a/queue-6.1/tcp-add-a-scheduling-point-in-established_get_first.patch b/queue-6.1/tcp-add-a-scheduling-point-in-established_get_first.patch
new file mode 100644 (file)
index 0000000..2ed2472
--- /dev/null
@@ -0,0 +1,59 @@
+From 9e8a8420178d9d36a834579bd7d9d7583b31343e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jul 2023 11:24:05 +0800
+Subject: tcp: add a scheduling point in established_get_first()
+
+From: Jian Wen <wenjianhn@gmail.com>
+
+[ Upstream commit 9f4a7c930284bf2b5b84d3636a8e88857149328f ]
+
+Kubernetes[1] is going to stick with /proc/net/tcp for a while.
+
+This commit reduces the scheduling latency introduced by
+established_get_first(), similar to commit acffb584cda7 ("net: diag:
+add a scheduling point in inet_diag_dump_icsk()").
+
+In our environment, the scheduling latency affects the performance of
+latency-sensitive services like Redis.
+
+Changes in V2 :
+ - call cond_resched() before checking if a bucket is empty as
+   suggested by Eric Dumazet
+ - removed the delay of synchronize_net() from the commit message
+
+[1] https://github.com/google/cadvisor/blob/v0.47.2/container/libcontainer/handler.go#L130
+
+Signed-off-by: Jian Wen <wenjian1@xiaomi.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Link: https://lore.kernel.org/r/20230711032405.3253025-1-wenjian1@xiaomi.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 00348cb9a211b..89200b4314018 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -57,6 +57,7 @@
+ #include <linux/init.h>
+ #include <linux/times.h>
+ #include <linux/slab.h>
++#include <linux/sched.h>
+ #include <net/net_namespace.h>
+ #include <net/icmp.h>
+@@ -2412,6 +2413,8 @@ static void *established_get_first(struct seq_file *seq)
+               struct hlist_nulls_node *node;
+               spinlock_t *lock = inet_ehash_lockp(hinfo, st->bucket);
++              cond_resched();
++
+               /* Lockless fast path for the common case of empty buckets */
+               if (empty_bucket(hinfo, st))
+                       continue;
+-- 
+2.53.0
+
diff --git a/queue-6.1/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch b/queue-6.1/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
new file mode 100644 (file)
index 0000000..17d337c
--- /dev/null
@@ -0,0 +1,72 @@
+From b46f82e783f2f0681bd1909b9108db735c1c0ce8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:17:38 +0800
+Subject: tcp: fix TFO max_qlen accounting across reuseport migration
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit a0ab2ba83e35159d81cec830a92e885ecf8139be ]
+
+A listener's TCP_FASTOPEN max_qlen stops being accurate and lets through
+far more pending Fast Open requests than it was configured for.
+
+This only shows up with SO_REUSEPORT listener migration, where closing a
+listener hands its still-pending TFO children over to a surviving one.
+
+fastopenq.qlen is charged in tcp_fastopen_create_child() when the child
+is created and uncharged in reqsk_fastopen_remove() when the handshake
+completes.  The uncharge follows rsk_listener of the request the child
+points at, and inet_reqsk_clone() has repointed the child at a new
+request owned by the new listener, so the ++ and the -- land on two
+different sockets.  The new listener's qlen drifts negative and its
+limit no longer binds.
+
+Charge the new listener during migration, like reqsk_queue_migrated()
+already does for queue->young and queue->qlen.
+
+Fixes: 54b92e841937 ("tcp: Migrate TCP_ESTABLISHED/TCP_SYN_RECV sockets in accept queues.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260803061739.134737-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index a275ab5321a96..a0014311c520c 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -927,11 +927,23 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
+       nreq->rsk_listener = sk;
+-      /* We need not acquire fastopenq->lock
+-       * because the child socket is locked in inet_csk_listen_stop().
+-       */
+-      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
++      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener) {
++              struct fastopen_queue *fastopenq;
++
++              /* reqsk_fastopen_remove() will uncharge nreq->rsk_listener,
++               * that is @sk, so charge it here.  Unlike the listener
++               * being closed, @sk is live and needs its lock.
++               */
++              fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
++              spin_lock_bh(&fastopenq->lock);
++              fastopenq->qlen++;
++              spin_unlock_bh(&fastopenq->lock);
++
++              /* We need not acquire fastopenq->lock
++               * because the child socket is locked in inet_csk_listen_stop().
++               */
+               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
++      }
+       return nreq;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-6.1/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..8357296
--- /dev/null
@@ -0,0 +1,45 @@
+From 63ed3bacda49ea105900dcc7ff518c9c99ff608e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 1b4e35dcb996b..5eec7c10acc20 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -457,7 +457,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-6.1/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-6.1/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..d8a45ea
--- /dev/null
@@ -0,0 +1,53 @@
+From 9fd99edd87f85f925d5d78255f681109cc34c539 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 35c014e10f24b..60fbb4ca34e00 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -21,17 +21,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-6.1/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch b/queue-6.1/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
new file mode 100644 (file)
index 0000000..34851e9
--- /dev/null
@@ -0,0 +1,56 @@
+From ba38e29ad91f4d3dbbe63dfe5142cba98e94c0d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:02:02 -0700
+Subject: vhost/vdpa: reject overflowing PA map page counts on 32-bit
+
+From: Yousef Alhouseen <alhouseenyousef@gmail.com>
+
+[ Upstream commit 0619aaa34c0c2a2dcb07f0e9c8a34e7efb8c4cdf ]
+
+vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
+size before computing the number of pages to pin. On 32-bit systems,
+where unsigned long is narrower than u64, that addition can overflow and
+the code can pin and map fewer pages than the requested IOTLB range.
+
+Reject sizes that overflow the unsigned long page-count calculation.
+
+Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and vhost_vdpa_pa_unmap()")
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index 7684c16e9e07a..df71ca25a1012 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -920,6 +920,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       unsigned int gup_flags = FOLL_LONGTERM;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
++      unsigned long page_offset;
+       u64 start = iova;
+       long pinned;
+       int ret = 0;
+@@ -932,7 +933,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       if (perm & VHOST_ACCESS_WO)
+               gup_flags |= FOLL_WRITE;
+-      npages = PFN_UP(size + (iova & ~PAGE_MASK));
++      page_offset = iova & ~PAGE_MASK;
++      if (size > ULONG_MAX - page_offset) {
++              ret = -EINVAL;
++              goto free;
++      }
++
++      npages = PFN_UP(size + page_offset);
+       if (!npages) {
+               ret = -EINVAL;
+               goto free;
+-- 
+2.53.0
+
diff --git a/queue-6.12/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch b/queue-6.12/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
new file mode 100644 (file)
index 0000000..26d449c
--- /dev/null
@@ -0,0 +1,39 @@
+From 00e90e1126706b1f5d9a21ddcc2adb8ca4d81471 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 14:57:22 -0700
+Subject: ARM: dts: BCM5301X: fix PCIe controller 2 second interrupt
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit bab4d538f8485e0d48538fcb82b285df3779278e ]
+
+PCIe controller 2 has interrupts 0-4 mapping to GIC SPI 138-142. The
+mapping for interrupt 1 was incorrectly set to 138 due to a copy-paste
+error. Fix it to 139.
+
+Assisted-by: opencode:big-pickle
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://lore.kernel.org/r/20260725215722.9323-1-rosenp@gmail.com
+Fixes: 3b3e35b279be ("ARM: dts: BCM5301X: Relicense AXI interrupts code to the GPL 2.0+ / MIT")
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/broadcom/bcm-ns.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+index d0d5f7e52a917..f08d0a27de0b4 100644
+--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
++++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+@@ -138,7 +138,7 @@ axi@18000000 {
+                       /* PCIe Controller 2 */
+                       <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+-                      <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
++                      <0x00014000 1 &gic GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+-- 
+2.53.0
+
diff --git a/queue-6.12/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-6.12/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..b18b978
--- /dev/null
@@ -0,0 +1,50 @@
+From 04d0bd8271e8d4919abe1bdbd73a4789a8a1e68f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 41891d3aa1247..4c1fc9983746c 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -32,6 +32,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -60,6 +61,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-6.12/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch b/queue-6.12/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch
new file mode 100644 (file)
index 0000000..6d1e52e
--- /dev/null
@@ -0,0 +1,52 @@
+From 043772828440f5fcf298190ad3f107baa002cc74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 21:45:27 +0100
+Subject: arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual
+ timer
+
+From: Daniel Drake <dan@reactivated.net>
+
+[ Upstream commit 75952cfc7752c52a2b692b59d34ce160d3edabb2 ]
+
+Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to EL2
+virtual timer when running VHE") causes boot to hang on Raspberry Pi 5.
+The newly-selected EL2 virtual timer does not generate any interrupts,
+even though the GIC_DIST_ENABLE_SET flag has been confirmed set via
+readback.
+
+It is highly unusual that this timer interrupt is non-operational because
+this is a standard GIC interrupt corresponding to a standard Cortex-A76
+CPU timer. However, Broadcom have confirmed for this SoC:
+
+> the interrupt line was never connected in the first place as this was
+> not identified as being a requirement
+
+Remove the corresponding DeviceTree entry.
+
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
+Fixes: faa3381267d0 ("arm64: dts: broadcom: Add minimal support for Raspberry Pi 5")
+Signed-off-by: Daniel Drake <dan@reactivated.net>
+Link: https://lore.kernel.org/r/20260716-bcm2712-el2-v2-1-e708f7fb42fa@reactivated.net
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+index 209f99b1ceae7..c8e809d77b3fe 100644
+--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
++++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+@@ -279,8 +279,6 @@ IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
+                                         IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
+-                                        IRQ_TYPE_LEVEL_LOW)>,
+-                           <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
+                                         IRQ_TYPE_LEVEL_LOW)>;
+       };
+ };
+-- 
+2.53.0
+
diff --git a/queue-6.12/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-6.12/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..b03499d
--- /dev/null
@@ -0,0 +1,52 @@
+From 6de6aaa202d283ccc747b28870d61ed42956dd2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 93882e976ede4..2a5ce46af5a0a 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -264,6 +264,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -285,8 +286,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-6.12/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch b/queue-6.12/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch
new file mode 100644 (file)
index 0000000..531302c
--- /dev/null
@@ -0,0 +1,155 @@
+From fb2de7155c33a54ebc8104369b5db136c6e8eb60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:34 -0700
+Subject: bnxt_en: Determine and store default RX ring in vnic structure
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 53f01cd594e223aabb538d5288e60111523c96f2 ]
+
+Each VNIC has a default RX ring.  The purpose of the default RX ring
+is to provide a destination for any packets that cannot be parsed by
+the RSS logic.  Up until now, the default RX ring is always Ring 0.
+
+We neglected to take care of this default RX ring when adding the
+queue restart feature.  If ring 0 (default ring) is re-started, it
+may now have a new FW ring ID after freeing the old one and
+allocating a new one.  The VNIC now may have a stale default ring
+and it may generate an internal exception.  This exception may
+appear in dmesg:
+
+FW reported unknown error type 10
+
+The best way to resolve this issue is to use a more appropriate
+ring for the default ring instead of always ring 0.  Ring 0 may not
+even be in the RSS table, especially on a new RSS context.
+
+This patch adds the logic to determine and store the proper default
+RX ring for a VNIC.  For an RSS VNIC, the default ring is the lowest
+ring number in the RSS table.  The next patch will add proper logic
+to update the VNIC if the default ring changes after queue restart.
+
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-3-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0b137529a899 ("bnxt_en: Refresh VNIC default ring on queue restart if needed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 33 +++++++++++++++--------
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h |  1 +
+ 2 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index ce7de01000160..31971a45ac3d4 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6365,25 +6365,36 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings)
+ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+ {
+       bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
+-      u16 i, j;
++      u16 i, j, min_j = bp->rx_nr_rings - 1;
+       if (!vnic->rss_table)
+-              return;
++              goto skip_rss_tbl;
+       /* Fill the RSS indirection table with ring group ids */
+       for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+               if (!no_rss)
+                       j = bp->rss_indir_tbl[i];
++              min_j = min(j, min_j);
+               vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]);
+       }
++
++skip_rss_tbl:
++      if (vnic->rss_table && !no_rss)
++              vnic->default_rx_ring = min_j;
++      else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
++              vnic->default_rx_ring = vnic->vnic_id - 1;
++      else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
++              vnic->default_rx_ring = bp->rx_nr_rings - 1;
++      else
++              vnic->default_rx_ring = 0;
+ }
+ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+                                   struct bnxt_vnic_info *vnic)
+ {
++      u16 tbl_size, i, min_j = bp->rx_nr_rings - 1;
+       __le16 *ring_tbl = vnic->rss_table;
+       struct bnxt_rx_ring_info *rxr;
+-      u16 tbl_size, i;
+       tbl_size = bnxt_get_rxfh_indir_size(bp->dev);
+@@ -6396,6 +6407,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+                       j = ethtool_rxfh_context_indir(vnic->rss_ctx)[i];
+               else
+                       j = bp->rss_indir_tbl[i];
++              min_j = min(j, min_j);
+               rxr = &bp->rx_ring[j];
+               ring_id = rxr->rx_ring_struct.fw_ring_id;
+@@ -6403,6 +6415,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+               ring_id = bnxt_cp_ring_for_rx(bp, rxr);
+               *ring_tbl++ = cpu_to_le16(ring_id);
+       }
++      vnic->default_rx_ring = min_j;
+ }
+ static void
+@@ -6600,8 +6613,9 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+               return rc;
+       if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+-              struct bnxt_rx_ring_info *rxr = &bp->rx_ring[0];
++              struct bnxt_rx_ring_info *rxr;
++              rxr = &bp->rx_ring[vnic->default_rx_ring];
+               req->default_rx_ring_id =
+                       cpu_to_le16(rxr->rx_ring_struct.fw_ring_id);
+               req->default_cmpl_ring_id =
+@@ -6634,13 +6648,7 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+               req->cos_rule = cpu_to_le16(0xffff);
+       }
+-      if (vnic->flags & BNXT_VNIC_RSS_FLAG)
+-              ring = 0;
+-      else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
+-              ring = vnic->vnic_id - 1;
+-      else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
+-              ring = bp->rx_nr_rings - 1;
+-
++      ring = vnic->default_rx_ring;
+       grp_idx = bp->rx_ring[ring].bnapi->index;
+       req->dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id);
+       req->lb_rule = cpu_to_le16(0xffff);
+@@ -10604,6 +10612,9 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt *bp)
+               return rc;
+       }
++      /* Setup the proper default RX ring */
++      bnxt_fill_hw_rss_tbl(bp, vnic);
++
+       rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+       if (rc) {
+               netdev_err(bp->dev, "Cannot allocate special vnic for NS2 A0: %x\n",
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 37fb74f18eeec..f50fe72f83ac6 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -1300,6 +1300,7 @@ struct bnxt_vnic_info {
+ #define BNXT_VNIC_RSSCTX_FLAG         0x40
+       struct ethtool_rxfh_context *rss_ctx;
+       u32             vnic_id;
++      u16             default_rx_ring;
+ };
+ struct bnxt_rss_ctx {
+-- 
+2.53.0
+
diff --git a/queue-6.12/bnxt_en-fix-ptp-pps-setting-bug.patch b/queue-6.12/bnxt_en-fix-ptp-pps-setting-bug.patch
new file mode 100644 (file)
index 0000000..c96adb2
--- /dev/null
@@ -0,0 +1,54 @@
+From 6cb21e23d9f2c83e3a40bd7a3326a06500b3c1a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:37 -0700
+Subject: bnxt_en: Fix PTP PPS setting bug
+
+From: Keegan Freyhof <keegan.freyhof@broadcom.com>
+
+[ Upstream commit 80eaf88efec33ac77ed7726d066c4f2f932cc329 ]
+
+The existing driver logic is always turning on PTP_CLK_REQ_PPS
+regardless of the "on" parameter passed to bnxt_ptp_enable().
+During shutdown, PTP_CLK_REQ_PPS may be turned off and this
+bug will do the opposite and may trigger a PCIe PTM request TLP.
+On some systems this can trigger a PCIe AER.
+
+Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on"
+parameter.
+
+Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index 6dfa0ab74c332..02276b9ac5c62 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -494,12 +494,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+               return rc;
+       case PTP_CLK_REQ_PPS:
+               /* Configure PHC PPS IN */
+-              rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
++              pin_id = 0;
++              if (!on)
++                      break;
++              rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+               if (rc)
+                       return rc;
+               rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
+               if (!rc)
+-                      ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
++                      ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL;
+               return rc;
+       default:
+               netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
+-- 
+2.53.0
+
diff --git a/queue-6.12/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch b/queue-6.12/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch
new file mode 100644 (file)
index 0000000..5d9b75b
--- /dev/null
@@ -0,0 +1,75 @@
+From 89afe7938643972de8d72e7efa0bef8090cc3614 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:33 -0700
+Subject: bnxt_en: Move RSS table fill outside __bnxt_hwrm_vnic_set_rss()
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 1d0fc6c7ea49994b8ff50d02979d1e4207ec6c4f ]
+
+This is a refactor patch with no change in behavior.  The caller
+will now fill the RSS table before calling __bnxt_hwrm_vnic_set_rss().
+In the next patch, we'll add code to determine the default ring for
+the VNIC when we fill the RSS table.
+
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-2-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0b137529a899 ("bnxt_en: Refresh VNIC default ring on queue restart if needed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 4970e20b2cb1b..ce7de01000160 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6367,6 +6367,9 @@ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+       bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
+       u16 i, j;
++      if (!vnic->rss_table)
++              return;
++
+       /* Fill the RSS indirection table with ring group ids */
+       for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+               if (!no_rss)
+@@ -6406,13 +6409,8 @@ static void
+ __bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req,
+                        struct bnxt_vnic_info *vnic)
+ {
+-      if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+-              bnxt_fill_hw_rss_tbl_p5(bp, vnic);
+-              if (bp->flags & BNXT_FLAG_CHIP_P7)
+-                      req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
+-      } else {
+-              bnxt_fill_hw_rss_tbl(bp, vnic);
+-      }
++      if (bp->flags & BNXT_FLAG_CHIP_P7)
++              req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
+       if (bp->rss_hash_delta) {
+               req->hash_type = cpu_to_le32(bp->rss_hash_delta);
+@@ -6464,6 +6462,7 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp,
+       if (!set_rss)
+               return hwrm_req_send(bp, req);
++      bnxt_fill_hw_rss_tbl_p5(bp, vnic);
+       __bnxt_hwrm_vnic_set_rss(bp, req, vnic);
+       ring_tbl_map = vnic->rss_table_dma_addr;
+       nr_ctxs = bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings);
+@@ -10299,6 +10298,7 @@ static int __bnxt_setup_vnic(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+       }
+ skip_rss_ctx:
++      bnxt_fill_hw_rss_tbl(bp, vnic);
+       /* configure default vnic, ring grp */
+       rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+       if (rc) {
+-- 
+2.53.0
+
diff --git a/queue-6.12/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch b/queue-6.12/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch
new file mode 100644 (file)
index 0000000..73649df
--- /dev/null
@@ -0,0 +1,46 @@
+From a00c79fd277fc35ea09d592e55766b979e1cd5cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:35 -0700
+Subject: bnxt_en: Refresh VNIC default ring on queue restart if needed
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 0b137529a8997caf67190ca1d71ba8bbdb44fbfb ]
+
+When a queue is restarted, refresh VNIC_CFG for all VNICs whose
+default RX ring is the restarted ring.  This will eliminate this
+possible FW warning caused by a stale default ring in the VNIC:
+
+FW reported unknown error type 10
+
+Fixes: 5ac066b7b062 ("bnxt_en: Fix queue start to update vnic RSS table")
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-4-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 31971a45ac3d4..2356b7ba7fcfb 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -10531,6 +10531,11 @@ static int bnxt_set_vnic_mru_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic,
+                                  vnic->vnic_id, rc);
+                       return rc;
+               }
++              if (rxr_id == vnic->default_rx_ring) {
++                      rc = bnxt_hwrm_vnic_cfg(bp, vnic);
++                      if (rc)
++                              return rc;
++              }
+       }
+       vnic->mru = mru;
+       bnxt_hwrm_vnic_update(bp, vnic,
+-- 
+2.53.0
+
diff --git a/queue-6.12/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-6.12/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..3ffa574
--- /dev/null
@@ -0,0 +1,80 @@
+From 27a457e89c78d1324b92e92ff0deb5395fe76840 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 7edf0fd58c346..ce6a3a0a2e153 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1535,8 +1535,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1598,9 +1598,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-6.12/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..612cab1
--- /dev/null
@@ -0,0 +1,74 @@
+From 436fac20447f0da139539fc8ce1882f9bba4f227 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 77183b436da5e..275c9fabc955e 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -13565,11 +13565,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
+@@ -13631,7 +13632,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -14490,8 +14491,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch b/queue-6.12/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch
new file mode 100644 (file)
index 0000000..906a7a2
--- /dev/null
@@ -0,0 +1,240 @@
+From 9ae64c65e362fdbae2f62491e7e87f50e6ed3cf1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:09 -0700
+Subject: bpf: tcp: Avoid socket skips and repeats during iteration
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit f5080f612a1c587bf636bb23d2a2f4de276d60e4 ]
+
+Replace the offset-based approach for tracking progress through a bucket
+in the TCP table with one based on socket cookies. Remember the cookies
+of unprocessed sockets from the last batch and use this list to
+pick up where we left off or, in the case that the next socket
+disappears between reads, find the first socket after that point that
+still exists in the bucket and resume from there.
+
+This approach guarantees that all sockets that existed when iteration
+began and continue to exist throughout will be visited exactly once.
+Sockets that are added to the table during iteration may or may not be
+seen, but if they are they will be seen exactly once.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 147 ++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 115 insertions(+), 32 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 6a8241367672b..7785c177f2cd3 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -58,6 +58,7 @@
+ #include <linux/times.h>
+ #include <linux/slab.h>
+ #include <linux/sched.h>
++#include <linux/sock_diag.h>
+ #include <net/net_namespace.h>
+ #include <net/icmp.h>
+@@ -3000,6 +3001,7 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ #ifdef CONFIG_BPF_SYSCALL
+ union bpf_tcp_iter_batch_item {
+       struct sock *sk;
++      __u64 cookie;
+ };
+ struct bpf_tcp_iter_state {
+@@ -3030,10 +3032,19 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
+ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ {
++      union bpf_tcp_iter_batch_item *item;
+       unsigned int cur_sk = iter->cur_sk;
++      __u64 cookie;
+-      while (cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[cur_sk++].sk);
++      /* Remember the cookies of the sockets we haven't seen yet, so we can
++       * pick up where we left off next time around.
++       */
++      while (cur_sk < iter->end_sk) {
++              item = &iter->batch[cur_sk++];
++              cookie = sock_gen_cookie(item->sk);
++              sock_gen_put(item->sk);
++              item->cookie = cookie;
++      }
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+@@ -3054,6 +3065,106 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+       return 0;
+ }
++static struct sock *bpf_iter_tcp_resume_bucket(struct sock *first_sk,
++                                             union bpf_tcp_iter_batch_item *cookies,
++                                             int n_cookies)
++{
++      struct hlist_nulls_node *node;
++      struct sock *sk;
++      int i;
++
++      for (i = 0; i < n_cookies; i++) {
++              sk = first_sk;
++              sk_nulls_for_each_from(sk, node)
++                      if (cookies[i].cookie == atomic64_read(&sk->sk_cookie))
++                              return sk;
++      }
++
++      return NULL;
++}
++
++static struct sock *bpf_iter_tcp_resume_listening(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      unsigned int find_cookie = iter->cur_sk;
++      unsigned int end_cookie = iter->end_sk;
++      int resume_bucket = st->bucket;
++      struct sock *sk;
++
++      if (end_cookie && find_cookie == end_cookie)
++              ++st->bucket;
++
++      sk = listening_get_first(seq);
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      if (sk && st->bucket == resume_bucket && end_cookie) {
++              sk = bpf_iter_tcp_resume_bucket(sk, &iter->batch[find_cookie],
++                                              end_cookie - find_cookie);
++              if (!sk) {
++                      spin_unlock(&hinfo->lhash2[st->bucket].lock);
++                      ++st->bucket;
++                      sk = listening_get_first(seq);
++              }
++      }
++
++      return sk;
++}
++
++static struct sock *bpf_iter_tcp_resume_established(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      unsigned int find_cookie = iter->cur_sk;
++      unsigned int end_cookie = iter->end_sk;
++      int resume_bucket = st->bucket;
++      struct sock *sk;
++
++      if (end_cookie && find_cookie == end_cookie)
++              ++st->bucket;
++
++      sk = established_get_first(seq);
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      if (sk && st->bucket == resume_bucket && end_cookie) {
++              sk = bpf_iter_tcp_resume_bucket(sk, &iter->batch[find_cookie],
++                                              end_cookie - find_cookie);
++              if (!sk) {
++                      spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
++                      ++st->bucket;
++                      sk = established_get_first(seq);
++              }
++      }
++
++      return sk;
++}
++
++static struct sock *bpf_iter_tcp_resume(struct seq_file *seq)
++{
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      struct sock *sk = NULL;
++
++      switch (st->state) {
++      case TCP_SEQ_STATE_LISTENING:
++              sk = bpf_iter_tcp_resume_listening(seq);
++              if (sk)
++                      break;
++              st->bucket = 0;
++              st->state = TCP_SEQ_STATE_ESTABLISHED;
++              fallthrough;
++      case TCP_SEQ_STATE_ESTABLISHED:
++              sk = bpf_iter_tcp_resume_established(seq);
++              break;
++      }
++
++      return sk;
++}
++
+ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+                                                struct sock **start_sk)
+ {
+@@ -3138,32 +3249,12 @@ static void bpf_iter_tcp_unlock_bucket(struct seq_file *seq)
+ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       unsigned int expected;
+       struct sock *sk;
+       int err;
+-      /* The st->bucket is done.  Directly advance to the next
+-       * bucket instead of having the tcp_seek_last_pos() to skip
+-       * one by one in the current bucket and eventually find out
+-       * it has to advance to the next bucket.
+-       */
+-      if (iter->end_sk && iter->cur_sk == iter->end_sk) {
+-              st->offset = 0;
+-              st->bucket++;
+-              if (st->state == TCP_SEQ_STATE_LISTENING &&
+-                  st->bucket > hinfo->lhash2_mask) {
+-                      st->state = TCP_SEQ_STATE_ESTABLISHED;
+-                      st->bucket = 0;
+-              }
+-      }
+-
+-      iter->cur_sk = 0;
+-      iter->end_sk = 0;
+-
+-      sk = tcp_seek_last_pos(seq);
++      sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+@@ -3179,10 +3270,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       if (err)
+               return ERR_PTR(err);
+-      iter->cur_sk = 0;
+-      iter->end_sk = 0;
+-
+-      sk = tcp_seek_last_pos(seq);
++      sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+@@ -3234,11 +3322,6 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+                * meta.seq_num is used instead.
+                */
+               st->num++;
+-              /* Move st->offset to the next sk in the bucket such that
+-               * the future start() will resume at st->offset in
+-               * st->bucket.  See tcp_seek_last_pos().
+-               */
+-              st->offset++;
+               sock_gen_put(iter->batch[iter->cur_sk++].sk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch b/queue-6.12/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
new file mode 100644 (file)
index 0000000..89e8670
--- /dev/null
@@ -0,0 +1,170 @@
+From 8d7757764746b30097751e52c837e09313d587df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:32:47 +0000
+Subject: bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()
+
+From: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+
+[ Upstream commit e5fd3f514e27db1f05fbd72ba615d74941e23c51 ]
+
+reqsk_queue_hash_req() publishes a TCP_NEW_SYN_RECV request_sock onto
+the ehash chain, drops the bucket lock, and only afterwards sets
+rsk_refcnt to 3.
+
+Lockless readers such as __inet_lookup_established() handle this with
+refcount_inc_not_zero(), but bpf_iter_tcp_established_batch() uses plain
+sock_hold() while holding the bucket lock, on the assumption that the
+lock guarantees sk_refcnt > 0. That assumption does not hold for
+request_sock:
+
+  CPU 0                                CPU 1
+  -----                                -----
+  tcp_conn_request()
+   reqsk_queue_hash_req()
+    inet_ehash_insert(req)
+     spin_lock(bucket)
+     __sk_nulls_add_node_rcu(req)      // rsk_refcnt == 0
+     spin_unlock(bucket)
+                                       bpf_iter_tcp_established_batch()
+                                        spin_lock(bucket)
+                                        sock_hold(req)   <-- addition on 0
+                                        spin_unlock(bucket)
+    refcount_set(&req->rsk_refcnt, 3)  // clobbers saturated value
+
+which surfaces as:
+
+  refcount_t: addition on 0; use-after-free.
+  WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x48/0x90, CPU#1
+  Call Trace:
+   bpf_iter_tcp_established_batch+0x14e/0x170
+   bpf_iter_tcp_batch+0x53/0x200
+   bpf_iter_tcp_seq_next+0x27/0x70
+   bpf_seq_read+0x107/0x410
+   vfs_read+0xb9/0x380
+
+The iterator's stolen reference is lost when the publishing CPU's
+refcount_set() overwrites the count, leaving the socket one reference
+short. When the last legitimate owner drops its reference the reqsk is
+freed while still reachable, leading to use-after-free.
+
+This reproduces in seconds with tcp_syncookies=0, a handful of threads
+doing connect()/close() to a local listener while others read an
+iter/tcp link in a tight loop.
+
+Use refcount_inc_not_zero() and skip the socket on failure. A skipped
+socket is still part of the bucket, so keep counting it in expected.
+The reallocations are sized from expected, and a request sock whose
+refcount gets published while the lock is held across the last realloc
+must already have room.
+
+A skipped socket is counted in expected but never batched, so end_sk
+can be short of expected on a batch that is actually complete. Decide
+completeness by whether the walk left any socket behind instead. The
+WARN after the locked realloc checks the same, replacing an
+end_sk == expected check that could not hold on that path since
+commit cdec67a489d4 ("bpf: tcp: Make sure iter->batch always
+contains a full bucket snapshot").
+
+If every matching socket in a bucket is mid-init (refcount 0), end_sk
+stays 0. Advance to the next bucket rather than returning a batch entry
+that was never filled this round.
+
+Fixes: 04c7820b776f ("bpf: tcp: Bpf iter batching and lock_sock")
+Assisted-by: Claude:unspecified
+Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://lore.kernel.org/bpf/20260730-bpf-iter-tcp-refcnt-v3-1-754b9c8a6717@linux.dev
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 43 ++++++++++++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 19 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 7785c177f2cd3..08154b1f4a8c4 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -3199,24 +3199,24 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+ {
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct hlist_nulls_node *node;
+-      unsigned int expected = 1;
+-      struct sock *sk;
+-
+-      sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++].sk = *start_sk;
++      struct sock *sk = *start_sk;
++      unsigned int expected = 0;
+-      sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+-              if (seq_sk_match(seq, sk)) {
+-                      if (iter->end_sk < iter->max_sk) {
+-                              sock_hold(sk);
+-                              iter->batch[iter->end_sk++].sk = sk;
+-                      } else if (!*start_sk) {
+-                              /* Remember where we left off. */
+-                              *start_sk = sk;
+-                      }
+-                      expected++;
++              if (!seq_sk_match(seq, sk))
++                      continue;
++              expected++;
++              if (iter->end_sk < iter->max_sk) {
++                      /* reqsk_queue_hash_req() inserts with sk_refcnt == 0
++                       * and refcount_set()s it after the bucket lock drops.
++                       */
++                      if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
++                              continue;
++                      iter->batch[iter->end_sk++].sk = sk;
++              } else if (!*start_sk) {
++                      /* Remember where we left off. */
++                      *start_sk = sk;
+               }
+       }
+@@ -3254,12 +3254,13 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       struct sock *sk;
+       int err;
++again:
+       sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was too small. */
+@@ -3275,7 +3276,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was still too small. Hold onto the lock while we try
+@@ -3288,10 +3289,14 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return ERR_PTR(err);
+       }
+-      expected = bpf_iter_fill_batch(seq, &sk);
+-      WARN_ON_ONCE(iter->end_sk != expected);
++      bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(sk);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
++      if (unlikely(!iter->end_sk)) {
++              ++iter->state.bucket;
++              goto again;
++      }
+       return iter->batch[0].sk;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-tcp-get-rid-of-st_bucket_done.patch b/queue-6.12/bpf-tcp-get-rid-of-st_bucket_done.patch
new file mode 100644 (file)
index 0000000..f8d96a5
--- /dev/null
@@ -0,0 +1,82 @@
+From 139dc03673e06ef584644ff2116efe20a1a97d4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:07 -0700
+Subject: bpf: tcp: Get rid of st_bucket_done
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit e25ab9b874a4bd8c6e3e5ce66cbe8a1dd4096e2e ]
+
+Get rid of the st_bucket_done field to simplify TCP iterator state and
+logic. Before, st_bucket_done could be false if bpf_iter_tcp_batch
+returned a partial batch; however, with the last patch ("bpf: tcp: Make
+sure iter->batch always contains a full bucket snapshot"),
+st_bucket_done == true is equivalent to iter->cur_sk == iter->end_sk.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 2bcc037521930..c18eee7ed5378 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -3004,7 +3004,6 @@ struct bpf_tcp_iter_state {
+       unsigned int end_sk;
+       unsigned int max_sk;
+       struct sock **batch;
+-      bool st_bucket_done;
+ };
+ struct bpf_iter__tcp {
+@@ -3027,8 +3026,10 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
+ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ {
+-      while (iter->cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[iter->cur_sk++]);
++      unsigned int cur_sk = iter->cur_sk;
++
++      while (cur_sk < iter->end_sk)
++              sock_gen_put(iter->batch[cur_sk++]);
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+@@ -3145,7 +3146,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+        * one by one in the current bucket and eventually find out
+        * it has to advance to the next bucket.
+        */
+-      if (iter->st_bucket_done) {
++      if (iter->end_sk && iter->cur_sk == iter->end_sk) {
+               st->offset = 0;
+               st->bucket++;
+               if (st->state == TCP_SEQ_STATE_LISTENING &&
+@@ -3157,7 +3158,6 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       iter->cur_sk = 0;
+       iter->end_sk = 0;
+-      iter->st_bucket_done = true;
+       sk = tcp_seek_last_pos(seq);
+       if (!sk)
+@@ -3305,10 +3305,8 @@ static void bpf_iter_tcp_seq_stop(struct seq_file *seq, void *v)
+                       (void)tcp_prog_seq_show(prog, &meta, v, 0);
+       }
+-      if (iter->cur_sk < iter->end_sk) {
++      if (iter->cur_sk < iter->end_sk)
+               bpf_iter_tcp_put_batch(iter);
+-              iter->st_bucket_done = false;
+-      }
+ }
+ static const struct seq_operations bpf_iter_tcp_seq_ops = {
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch b/queue-6.12/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch
new file mode 100644 (file)
index 0000000..ff7a98f
--- /dev/null
@@ -0,0 +1,64 @@
+From 009d9d25c6e9cbf1db069fb3ff0686e37c2a939b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:05 -0700
+Subject: bpf: tcp: Make mem flags configurable through
+ bpf_iter_tcp_realloc_batch
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit 8271bec9fc1cfe522b1a18cacbefd6712a3d41c2 ]
+
+Prepare for the next patch which needs to be able to choose either
+GFP_USER or GFP_NOWAIT for calls to bpf_iter_tcp_realloc_batch.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index a9f3ee89302ce..cffa0fc1ae6e1 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -3032,12 +3032,12 @@ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+-                                    unsigned int new_batch_sz)
++                                    unsigned int new_batch_sz, gfp_t flags)
+ {
+       struct sock **new_batch;
+       new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
+-                           GFP_USER | __GFP_NOWARN);
++                           flags | __GFP_NOWARN);
+       if (!new_batch)
+               return -ENOMEM;
+@@ -3149,7 +3149,8 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return sk;
+       }
+-      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2)) {
++      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
++                                                  GFP_USER)) {
+               resized = true;
+               goto again;
+       }
+@@ -3578,7 +3579,7 @@ static int bpf_iter_init_tcp(void *priv_data, struct bpf_iter_aux_info *aux)
+       if (err)
+               return err;
+-      err = bpf_iter_tcp_realloc_batch(iter, INIT_BATCH_SZ);
++      err = bpf_iter_tcp_realloc_batch(iter, INIT_BATCH_SZ, GFP_USER);
+       if (err) {
+               bpf_iter_fini_seq_net(priv_data);
+               return err;
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch b/queue-6.12/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch
new file mode 100644 (file)
index 0000000..f3a9bee
--- /dev/null
@@ -0,0 +1,257 @@
+From f3e42445ab9d1223446821a4e07ebd1692bfd80b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:06 -0700
+Subject: bpf: tcp: Make sure iter->batch always contains a full bucket
+ snapshot
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit cdec67a489d4fdae3e83e04fca0419136a83c4c2 ]
+
+Require that iter->batch always contains a full bucket snapshot. This
+invariant is important to avoid skipping or repeating sockets during
+iteration when combined with the next few patches. Before, there were
+two cases where a call to bpf_iter_tcp_batch may only capture part of a
+bucket:
+
+1. When bpf_iter_tcp_realloc_batch() returns -ENOMEM.
+2. When more sockets are added to the bucket while calling
+   bpf_iter_tcp_realloc_batch(), making the updated batch size
+   insufficient.
+
+In cases where the batch size only covers part of a bucket, it is
+possible to forget which sockets were already visited, especially if we
+have to process a bucket in more than two batches. This forces us to
+choose between repeating or skipping sockets, so don't allow this:
+
+1. Stop iteration and propagate -ENOMEM up to userspace if reallocation
+   fails instead of continuing with a partial batch.
+2. Try bpf_iter_tcp_realloc_batch() with GFP_USER just as before, but if
+   we still aren't able to capture the full bucket, call
+   bpf_iter_tcp_realloc_batch() again while holding the bucket lock to
+   guarantee the bucket does not change. On the second attempt use
+   GFP_NOWAIT since we hold onto the spin lock.
+
+I did some manual testing to exercise the code paths where GFP_NOWAIT is
+used and where ERR_PTR(err) is returned. I used the realloc test cases
+included later in this series to trigger a scenario where a realloc
+happens inside bpf_iter_tcp_batch and made a small code tweak to force
+the first realloc attempt to allocate a too-small batch, thus requiring
+another attempt with GFP_NOWAIT. Some printks showed both reallocs with
+the tests passing:
+
+Jun 27 00:00:53 crow kernel: again GFP_USER
+Jun 27 00:00:53 crow kernel: again GFP_NOWAIT
+Jun 27 00:00:53 crow kernel: again GFP_USER
+Jun 27 00:00:53 crow kernel: again GFP_NOWAIT
+
+With this setup, I also forced each of the bpf_iter_tcp_realloc_batch
+calls to return -ENOMEM to ensure that iteration ends and that the
+read() in userspace fails.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 109 +++++++++++++++++++++++++++++++-------------
+ 1 file changed, 77 insertions(+), 32 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index cffa0fc1ae6e1..2bcc037521930 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -3041,7 +3041,7 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+       if (!new_batch)
+               return -ENOMEM;
+-      bpf_iter_tcp_put_batch(iter);
++      memcpy(new_batch, iter->batch, sizeof(*iter->batch) * iter->end_sk);
+       kvfree(iter->batch);
+       iter->batch = new_batch;
+       iter->max_sk = new_batch_sz;
+@@ -3050,69 +3050,95 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+ }
+ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+-                                               struct sock *start_sk)
++                                               struct sock **start_sk)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       struct hlist_nulls_node *node;
+       unsigned int expected = 1;
+       struct sock *sk;
+-      sock_hold(start_sk);
+-      iter->batch[iter->end_sk++] = start_sk;
++      sock_hold(*start_sk);
++      iter->batch[iter->end_sk++] = *start_sk;
+-      sk = sk_nulls_next(start_sk);
++      sk = sk_nulls_next(*start_sk);
++      *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+                               iter->batch[iter->end_sk++] = sk;
++                      } else if (!*start_sk) {
++                              /* Remember where we left off. */
++                              *start_sk = sk;
+                       }
+                       expected++;
+               }
+       }
+-      spin_unlock(&hinfo->lhash2[st->bucket].lock);
+       return expected;
+ }
+ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+-                                                 struct sock *start_sk)
++                                                 struct sock **start_sk)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       struct hlist_nulls_node *node;
+       unsigned int expected = 1;
+       struct sock *sk;
+-      sock_hold(start_sk);
+-      iter->batch[iter->end_sk++] = start_sk;
++      sock_hold(*start_sk);
++      iter->batch[iter->end_sk++] = *start_sk;
+-      sk = sk_nulls_next(start_sk);
++      sk = sk_nulls_next(*start_sk);
++      *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+                               iter->batch[iter->end_sk++] = sk;
++                      } else if (!*start_sk) {
++                              /* Remember where we left off. */
++                              *start_sk = sk;
+                       }
+                       expected++;
+               }
+       }
+-      spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
+       return expected;
+ }
++static unsigned int bpf_iter_fill_batch(struct seq_file *seq,
++                                      struct sock **start_sk)
++{
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++
++      if (st->state == TCP_SEQ_STATE_LISTENING)
++              return bpf_iter_tcp_listening_batch(seq, start_sk);
++      else
++              return bpf_iter_tcp_established_batch(seq, start_sk);
++}
++
++static void bpf_iter_tcp_unlock_bucket(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++
++      if (st->state == TCP_SEQ_STATE_LISTENING)
++              spin_unlock(&hinfo->lhash2[st->bucket].lock);
++      else
++              spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
++}
++
+ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+ {
+       struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct tcp_iter_state *st = &iter->state;
+       unsigned int expected;
+-      bool resized = false;
+       struct sock *sk;
++      int err;
+       /* The st->bucket is done.  Directly advance to the next
+        * bucket instead of having the tcp_seek_last_pos() to skip
+@@ -3129,33 +3155,52 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               }
+       }
+-again:
+-      /* Get a new batch */
+       iter->cur_sk = 0;
+       iter->end_sk = 0;
+-      iter->st_bucket_done = false;
++      iter->st_bucket_done = true;
+       sk = tcp_seek_last_pos(seq);
+       if (!sk)
+               return NULL; /* Done */
+-      if (st->state == TCP_SEQ_STATE_LISTENING)
+-              expected = bpf_iter_tcp_listening_batch(seq, sk);
+-      else
+-              expected = bpf_iter_tcp_established_batch(seq, sk);
++      expected = bpf_iter_fill_batch(seq, &sk);
++      if (likely(iter->end_sk == expected))
++              goto done;
+-      if (iter->end_sk == expected) {
+-              iter->st_bucket_done = true;
+-              return sk;
+-      }
++      /* Batch size was too small. */
++      bpf_iter_tcp_unlock_bucket(seq);
++      bpf_iter_tcp_put_batch(iter);
++      err = bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
++                                       GFP_USER);
++      if (err)
++              return ERR_PTR(err);
++
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      sk = tcp_seek_last_pos(seq);
++      if (!sk)
++              return NULL; /* Done */
++
++      expected = bpf_iter_fill_batch(seq, &sk);
++      if (likely(iter->end_sk == expected))
++              goto done;
+-      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
+-                                                  GFP_USER)) {
+-              resized = true;
+-              goto again;
++      /* Batch size was still too small. Hold onto the lock while we try
++       * again with a larger batch to make sure the current bucket's size
++       * does not change in the meantime.
++       */
++      err = bpf_iter_tcp_realloc_batch(iter, expected, GFP_NOWAIT);
++      if (err) {
++              bpf_iter_tcp_unlock_bucket(seq);
++              return ERR_PTR(err);
+       }
+-      return sk;
++      expected = bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(iter->end_sk != expected);
++done:
++      bpf_iter_tcp_unlock_bucket(seq);
++      return iter->batch[0];
+ }
+ static void *bpf_iter_tcp_seq_start(struct seq_file *seq, loff_t *pos)
+-- 
+2.53.0
+
diff --git a/queue-6.12/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch b/queue-6.12/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch
new file mode 100644 (file)
index 0000000..fcec70d
--- /dev/null
@@ -0,0 +1,124 @@
+From 7e3b3d5ea0bbccea9dc8004d4d619bcaa8ec62f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:08 -0700
+Subject: bpf: tcp: Use bpf_tcp_iter_batch_item for bpf_tcp_iter_state batch
+ items
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit efeb820951ebf3778830256496ff72d00d135310 ]
+
+Prepare for the next patch that tracks cookies between iterations by
+converting struct sock **batch to union bpf_tcp_iter_batch_item *batch
+inside struct bpf_tcp_iter_state.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index c18eee7ed5378..6a8241367672b 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2998,12 +2998,16 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ }
+ #ifdef CONFIG_BPF_SYSCALL
++union bpf_tcp_iter_batch_item {
++      struct sock *sk;
++};
++
+ struct bpf_tcp_iter_state {
+       struct tcp_iter_state state;
+       unsigned int cur_sk;
+       unsigned int end_sk;
+       unsigned int max_sk;
+-      struct sock **batch;
++      union bpf_tcp_iter_batch_item *batch;
+ };
+ struct bpf_iter__tcp {
+@@ -3029,13 +3033,13 @@ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+       unsigned int cur_sk = iter->cur_sk;
+       while (cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[cur_sk++]);
++              sock_gen_put(iter->batch[cur_sk++].sk);
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+                                     unsigned int new_batch_sz, gfp_t flags)
+ {
+-      struct sock **new_batch;
++      union bpf_tcp_iter_batch_item *new_batch;
+       new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
+                            flags | __GFP_NOWARN);
+@@ -3059,7 +3063,7 @@ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+       struct sock *sk;
+       sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++] = *start_sk;
++      iter->batch[iter->end_sk++].sk = *start_sk;
+       sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+@@ -3067,7 +3071,7 @@ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+-                              iter->batch[iter->end_sk++] = sk;
++                              iter->batch[iter->end_sk++].sk = sk;
+                       } else if (!*start_sk) {
+                               /* Remember where we left off. */
+                               *start_sk = sk;
+@@ -3088,7 +3092,7 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+       struct sock *sk;
+       sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++] = *start_sk;
++      iter->batch[iter->end_sk++].sk = *start_sk;
+       sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+@@ -3096,7 +3100,7 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+-                              iter->batch[iter->end_sk++] = sk;
++                              iter->batch[iter->end_sk++].sk = sk;
+                       } else if (!*start_sk) {
+                               /* Remember where we left off. */
+                               *start_sk = sk;
+@@ -3200,7 +3204,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       WARN_ON_ONCE(iter->end_sk != expected);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
+-      return iter->batch[0];
++      return iter->batch[0].sk;
+ }
+ static void *bpf_iter_tcp_seq_start(struct seq_file *seq, loff_t *pos)
+@@ -3235,11 +3239,11 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+                * st->bucket.  See tcp_seek_last_pos().
+                */
+               st->offset++;
+-              sock_gen_put(iter->batch[iter->cur_sk++]);
++              sock_gen_put(iter->batch[iter->cur_sk++].sk);
+       }
+       if (iter->cur_sk < iter->end_sk)
+-              sk = iter->batch[iter->cur_sk];
++              sk = iter->batch[iter->cur_sk].sk;
+       else
+               sk = bpf_iter_tcp_batch(seq);
+-- 
+2.53.0
+
diff --git a/queue-6.12/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch b/queue-6.12/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
new file mode 100644 (file)
index 0000000..b055568
--- /dev/null
@@ -0,0 +1,96 @@
+From 85600276fea216f797cf6d957f07becd1f798476 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 14:53:52 +0300
+Subject: btrfs: fix memory leak in btrfs_do_encoded_write()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit d2a4e4e626b2f4670b69b430c357f03f53eb6632 ]
+
+Local fuzzing of 6.12.94 has found the following memory leak:
+
+Unreferenced object 0xffff888018050a80 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 10 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
+    10 0a 05 18 80 88 ff ff 10 0a 05 18 80 88 ff ff  ................
+  backtrace (crc a8a6fc29):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    extent_changeset_alloc fs/btrfs/extent_io.h:207 [inline]
+    qgroup_reserve_data+0x1c5/0x7d0 fs/btrfs/qgroup.c:4305
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Unreferenced object 0xffff888018050a00 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 ff 0f 00 00 00 00 00 00  ................
+    90 0a 05 18 80 88 ff ff 90 0a 05 18 80 88 ff ff  ................
+  backtrace (crc cb5c9580):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    kzalloc_noprof include/linux/slab.h:1014 [inline]
+    ulist_prealloc+0x9c/0x110 fs/btrfs/ulist.c:114
+    extent_changeset_prealloc fs/btrfs/extent_io.h:217 [inline]
+    __set_extent_bit+0x16b/0x1a70 fs/btrfs/extent-io-tree.c:1086
+    set_record_extent_bits+0x50/0x90 fs/btrfs/extent-io-tree.c:1821
+    qgroup_reserve_data+0x274/0x7d0 fs/btrfs/qgroup.c:4312
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fix this by freeing an extent changeset before returning from
+btrfs_do_encoded_write().
+
+Fixes: 7c0c7269f7b5 ("btrfs: add BTRFS_IOC_ENCODED_WRITE")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index f60f8bf38dc50..ab7f19ca21457 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -9684,6 +9684,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
+       }
+       kvfree(folios);
+ out:
++      extent_changeset_free(data_reserved);
+       if (ret >= 0)
+               iocb->ki_pos += encoded->len;
+       return ret;
+-- 
+2.53.0
+
diff --git a/queue-6.12/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-6.12/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..7b3a73f
--- /dev/null
@@ -0,0 +1,70 @@
+From 9c6d694eb55ebc03717e944215ae8b4df9955e92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 461f57f66631c..fbd1afe178a36 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -309,7 +309,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
+@@ -343,7 +343,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-6.12/devlink-fix-net-namespace-reference-leak-in-reload.patch b/queue-6.12/devlink-fix-net-namespace-reference-leak-in-reload.patch
new file mode 100644 (file)
index 0000000..b3c205b
--- /dev/null
@@ -0,0 +1,42 @@
+From 1f8dec0746a763ff605a09a5f978abfb1954dab6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:06:00 +0300
+Subject: devlink: fix net namespace reference leak in reload
+
+From: Or Har-Toov <ohartoov@nvidia.com>
+
+[ Upstream commit 1c4dac9bf1d2ac31da63b794bdec697777cbd0fd ]
+
+devlink_nl_reload_doit() calls devlink_netns_get(), which returns a net
+with a held reference. When the requested namespace differs from the
+current one and the reload action is not DRIVER_REINIT, the function
+returns -EOPNOTSUPP without releasing the reference. Add the missing
+put_net() on this error path.
+
+Fixes: 2edd92570441 ("devlink: don't allow to change net namespace for FW_ACTIVATE reload action")
+Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260729080600.2427721-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/dev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/devlink/dev.c b/net/devlink/dev.c
+index 13c73f50da3d1..fc109acd4e844 100644
+--- a/net/devlink/dev.c
++++ b/net/devlink/dev.c
+@@ -579,6 +579,7 @@ int devlink_nl_reload_doit(struct sk_buff *skb, struct genl_info *info)
+                   action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Changing namespace is only supported for reinit action");
++                      put_net(dest_net);
+                       return -EOPNOTSUPP;
+               }
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.12/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch b/queue-6.12/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
new file mode 100644 (file)
index 0000000..0135d6e
--- /dev/null
@@ -0,0 +1,79 @@
+From 832ccf4113810dad4ebb60a53cab7ed017244a79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:38:06 +0800
+Subject: drm/bridge: ps8640: propagate AUX transfer register errors
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 20697ecb299cd77b4cf8b28f655e56606b0472d8 ]
+
+ps8640_aux_transfer_msg() programs the AUX address registers, starts the
+AUX transfer, waits for SWAUX_SEND to clear, and reads the AUX status
+register. Several of those regmap operations have return values, but the
+function only checks a stale ret after the status read.
+
+Propagate failures from the address write, transfer start, completion
+poll, and status read. This avoids returning a transfer length when the
+bridge register transaction or AUX completion wait failed.
+
+Fixes: 13afcdd7277e ("drm/bridge: parade-ps8640: Add support for AUX channel")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patch.msgid.link/20260723103509.2-ps8640-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/parade-ps8640.c | 27 ++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
+index 14d4dcf239da8..61ea855e55d87 100644
+--- a/drivers/gpu/drm/bridge/parade-ps8640.c
++++ b/drivers/gpu/drm/bridge/parade-ps8640.c
+@@ -258,8 +258,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+       addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD :
+                                             ((len - 1) & SWAUX_LENGTH_MASK);
+-      regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
+-                        ARRAY_SIZE(addr_len));
++      ret = regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
++                              ARRAY_SIZE(addr_len));
++      if (ret) {
++              DRM_DEV_ERROR(dev,
++                            "failed to write AUX address %#x, len %zu: %d\n",
++                            msg->address, len, ret);
++              return ret;
++      }
+       if (len && (request == DP_AUX_NATIVE_WRITE ||
+                   request == DP_AUX_I2C_WRITE)) {
+@@ -275,13 +281,22 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+               }
+       }
+-      regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      ret = regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to start AUX transfer: %d\n", ret);
++              return ret;
++      }
+       /* Zero delay loop because i2c transactions are slow already */
+-      regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
+-                               !(data & SWAUX_SEND), 0, 50 * 1000);
++      ret = regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
++                                     !(data & SWAUX_SEND), 0, 50 * 1000);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to complete AUX transfer: %d\n",
++                            ret);
++              return ret;
++      }
+-      regmap_read(map, PAGE0_SWAUX_STATUS, &data);
++      ret = regmap_read(map, PAGE0_SWAUX_STATUS, &data);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n",
+                             ret);
+-- 
+2.53.0
+
diff --git a/queue-6.12/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch b/queue-6.12/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch
new file mode 100644 (file)
index 0000000..53dfc21
--- /dev/null
@@ -0,0 +1,49 @@
+From 09810a3f6ddacb2cfe1759de76979bac22a5cf8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 23:26:30 -0700
+Subject: enic: fix tx_hang_reset use-after-free on device removal
+
+From: Satish Kharat <satishkh@cisco.com>
+
+[ Upstream commit ec680ea4ba1bca92a767fb7e7869758bfdd886e3 ]
+
+enic_remove() cancels the reset and change_mtu_work items but does not
+cancel tx_hang_reset. A TX timeout that fires while the device is being
+removed can schedule enic_tx_hang_reset() so that it runs after
+free_netdev(), resulting in a use-after-free.
+
+cancel_work_sync() alone is not sufficient here: the still-live watchdog
+and notify paths can re-schedule these work items in the window between
+the cancel and unregister_netdev(). Use disable_work_sync(), which
+cancels the work and blocks any subsequent schedule_work() from
+requeuing it, and apply it to the reset and change_mtu_work items as
+well so the same requeue race is closed for all teardown work.
+
+Fixes: 937317c7c109 ("enic: do hang reset only in case of tx timeout")
+Signed-off-by: Satish Kharat <satishkh@cisco.com>
+Link: https://patch.msgid.link/20260728062730.2394873-1-satishkh@cisco.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/cisco/enic/enic_main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
+index a432783756d8c..e474cef720630 100644
+--- a/drivers/net/ethernet/cisco/enic/enic_main.c
++++ b/drivers/net/ethernet/cisco/enic/enic_main.c
+@@ -3141,8 +3141,9 @@ static void enic_remove(struct pci_dev *pdev)
+       if (netdev) {
+               struct enic *enic = netdev_priv(netdev);
+-              cancel_work_sync(&enic->reset);
+-              cancel_work_sync(&enic->change_mtu_work);
++              disable_work_sync(&enic->reset);
++              disable_work_sync(&enic->tx_hang_reset);
++              disable_work_sync(&enic->change_mtu_work);
+               unregister_netdev(netdev);
+               enic_dev_deinit(enic);
+               vnic_dev_close(enic->vdev);
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-ads7828-fix-external-vref-regulator-handling.patch b/queue-6.12/hwmon-ads7828-fix-external-vref-regulator-handling.patch
new file mode 100644 (file)
index 0000000..e2833eb
--- /dev/null
@@ -0,0 +1,71 @@
+From 63cb1925c4569549cbef27de999074df14cb6d51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 14:16:45 +0800
+Subject: hwmon: (ads7828) Fix external VREF regulator handling
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit fddb5ceaf901b050ed2a1a7deeecbf97e003435a ]
+
+The driver currently has two issues with the external VREF regulator
+handling in ads7828_probe():
+
+1. All errors from devm_regulator_get_optional() are ignored, causing the
+   driver to incorrectly fall back to internal VREF even for transient
+   errors like -EPROBE_DEFER or genuine failures like -ENOMEM.
+
+2. The external regulator is never enabled. The driver calls
+   regulator_get_voltage() without first calling regulator_enable(),
+   so the VREF pin may remain unpowered if the regulator is not
+   configured as always-on.
+
+Fix both issues by switching to devm_regulator_get_enable_read_voltage(),
+which handles regulator get, enable, and voltage read in one call.
+Only -ENODEV (no regulator specified in device tree) should trigger the
+fallback to internal VREF. All other errors are propagated to the caller.
+
+Fixes: a8ddfea09566 ("hwmon: (ads7828) Accept optional parameters from device tree")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260805061645.1331652-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ads7828.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
+index 436637264056c..20ef4992f5bb8 100644
+--- a/drivers/hwmon/ads7828.c
++++ b/drivers/hwmon/ads7828.c
+@@ -106,12 +106,11 @@ static int ads7828_probe(struct i2c_client *client)
+       struct ads7828_data *data;
+       struct device *hwmon_dev;
+       unsigned int vref_mv = ADS7828_INT_VREF_MV;
+-      unsigned int vref_uv;
++      int vref_uv;
+       bool diff_input = false;
+       bool ext_vref = false;
+       unsigned int regval;
+       enum ads7828_chips chip;
+-      struct regulator *reg;
+       data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
+       if (!data)
+@@ -125,9 +124,11 @@ static int ads7828_probe(struct i2c_client *client)
+       } else if (dev->of_node) {
+               diff_input = of_property_read_bool(dev->of_node,
+                                                  "ti,differential-input");
+-              reg = devm_regulator_get_optional(dev, "vref");
+-              if (!IS_ERR(reg)) {
+-                      vref_uv = regulator_get_voltage(reg);
++              vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref");
++              if (vref_uv < 0) {
++                      if (vref_uv != -ENODEV)
++                              return vref_uv;
++              } else {
+                       vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
+                       if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
+                           vref_mv > ADS7828_EXT_VREF_MV_MAX)
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch b/queue-6.12/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
new file mode 100644 (file)
index 0000000..67049eb
--- /dev/null
@@ -0,0 +1,50 @@
+From fb2a43eb8e0a907cfa44b6b6e519a4ab1efd0205 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 07:19:20 +0000
+Subject: hwmon: (corsair-psu) fix possible out-of-bounds access on missing
+ string termination
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit 36c4d73ce05d1d8896c2669eb0730d35a02a2ec1 ]
+
+In theory it could be possible that the REPLY_SIZE sized buffers for
+holding the vendor and product strings could be end up missing the null
+termination (for example by malicious hardware built on purpose)
+required by the seq_printf() call. That limits the debugfs printf calls
+to a maximum string length of REPLY_SIZE.
+
+Fixes: d115b51e0e567 ("hwmon: add Corsair PSU HID controller driver")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/anLj9gPWRoRDbQBV@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 4ab73bcef1d12..61d1b22bc63ec 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -709,7 +709,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->vendor);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
+       return 0;
+ }
+@@ -719,7 +719,7 @@ static int product_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->product);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch b/queue-6.12/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch
new file mode 100644 (file)
index 0000000..b3e3840
--- /dev/null
@@ -0,0 +1,105 @@
+From eb613b8de08db6dfaadc9ff4e30e052f0a5e98f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:42:42 -0700
+Subject: hwmon: (ltc4282) Avoid overflow in maximum power calculation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit edd11a94335747423569500a194c6eaa915f2963 ]
+
+During device initialization in ltc4282_set_max_limits(), the calculation
+of the maximum power limit can suffer from a 32-bit integer overflow.
+
+static int ltc4282_set_max_limits(struct ltc4282_state *st)
+{
+    ...
+    st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI,
+                                      st->rsense) * st->vfs_out;
+    ...
+}
+
+The result of DIV_ROUND_CLOSEST() evaluates to a 32-bit unsigned integer
+on 32-bit architectures. This result is then multiplied by st->vfs_out,
+which is a 16-bit unsigned integer. According to C promotion rules, since
+both operands are 32-bit or smaller, the multiplication is performed in
+32-bit precision.
+
+If the device is configured with a low sense resistor value via the device
+tree (for example, 100 nano-ohms, resulting in st->rsense = 1) and the
+voltage is high, the division result can reach 343,750,000 and st->vfs_out
+can be 33,280. The product of these values is approximately 11.44 trillion,
+which exceeds the maximum capacity of a 32-bit integer and overflows
+before being stored in st->power_max.
+
+This overflow causes a truncated value to be assigned to st->power_max and
+written to the hardware limit register. An incorrect maximum power limit
+can trigger spurious power-bad faults or alarms, which may lead to the
+shutdown of the monitored power rail.
+
+Avoid the problem by calculating and storing the maximum power using 64-bit
+variables.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index e1c0d02b564b7..93e08bde29aa9 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -142,7 +142,7 @@ struct ltc4282_state {
+        */
+       struct ltc4282_cache in0_1_cache[LTC4282_CHAN_VGPIO];
+       u32 vsense_max;
+-      long power_max;
++      s64 power_max;
+       u32 rsense;
+       u16 vdd;
+       u16 vfs_out;
+@@ -621,13 +621,12 @@ static int ltc4282_read(struct device *dev, enum hwmon_sensor_types type,
+ }
+ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
+-                                  long val)
++                                  s64 val)
+ {
+       u32 power;
+       u64 temp;
+-      if (val > st->power_max)
+-              val = st->power_max;
++      val = clamp(val, 0, st->power_max);
+       temp = val * int_pow(U8_MAX, 2) * st->rsense;
+       power = DIV64_U64_ROUND_CLOSEST(temp,
+@@ -637,7 +636,7 @@ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
+ }
+ static int ltc4282_write_power_word(const struct ltc4282_state *st, u32 reg,
+-                                  long val)
++                                  u64 val)
+ {
+       u64 temp = int_pow(U16_MAX, 2) * st->rsense, temp_2;
+       __be16 __raw;
+@@ -1254,7 +1253,8 @@ static int ltc4282_set_max_limits(struct ltc4282_state *st)
+               return ret;
+       /* Power is given by ISENSE * Vout. */
+-      st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI, st->rsense) * st->vfs_out;
++      st->power_max = DIV_ROUND_CLOSEST_ULL((u64)st->vsense_max * DECA * MILLI,
++                                            st->rsense) * st->vfs_out;
+       ret = ltc4282_write_power_byte(st, LTC4282_POWER_MAX, st->power_max);
+       if (ret)
+               return ret;
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-ltc4282-clamp-negative-current-limits.patch b/queue-6.12/hwmon-ltc4282-clamp-negative-current-limits.patch
new file mode 100644 (file)
index 0000000..3acca3e
--- /dev/null
@@ -0,0 +1,69 @@
+From d786a3cac4126469ec120c715d6dc3151c38c5e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 16:26:05 -0700
+Subject: hwmon: (ltc4282) Clamp negative current limits
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit e253dd5f9f6d875a317895bf43ec9534ed7523cb ]
+
+When a negative value is passed to ltc4282_write_curr(), the signed long
+val is cast directly to u64:
+
+drivers/hwmon/ltc4282.c:ltc4282_write_curr() {
+        /* need to pass it in millivolt */
+        u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
+        ...
+}
+
+This cast converts negative inputs into large positive values. The
+subsequent division result overflows the u32 in variable, truncating
+to a pseudo-random positive value. When this is passed to
+ltc4282_write_voltage_byte(), it is clamped to the maximum limit instead
+of zero.
+
+Clamp val to 0 and to the maximum supported upper limit before the cast
+and assign the result to a 64-bit temporary variable before the division
+to avoid the underflow and an also possible overflow.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index 93e08bde29aa9..0e7449db3158f 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -15,6 +15,7 @@
+ #include <linux/hwmon-sysfs.h>
+ #include <linux/i2c.h>
+ #include <linux/math.h>
++#include <linux/math64.h>
+ #include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/mod_devicetable.h>
+@@ -945,8 +946,11 @@ static int ltc4282_curr_reset_hist(struct ltc4282_state *st)
+ static int ltc4282_write_curr(struct ltc4282_state *st, u32 attr,
+                             long val)
+ {
++      s32 ulimit = min_t(u64, INT_MAX,
++                         div_u64((u64)INT_MAX * DECA * MICRO, st->rsense));
++      u64 val64 = clamp(val, 0, ulimit);
+       /* need to pass it in millivolt */
+-      u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
++      u32 in = DIV_ROUND_CLOSEST_ULL(val64 * st->rsense, DECA * MICRO);
+       switch (attr) {
+       case hwmon_curr_max:
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch b/queue-6.12/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch
new file mode 100644 (file)
index 0000000..57b444f
--- /dev/null
@@ -0,0 +1,68 @@
+From 32ff69a79971fb12637f5867ef4de8ebf635cda4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 17:30:42 -0700
+Subject: hwmon: (ltc4282) Fix parsing adi,current-limit-sense-microvolt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 335698fd7f60b6707b21fda725f97f35fa956b07 ]
+
+ltc4282_parse_dt() evaluates the wrong variable when parsing the current
+limit.
+
+When the adi,current-limit-sense-microvolt property is parsed into
+st->vsense_max, the subsequent switch statement evaluates the unrelated
+val variable instead of st->vsense_max:
+
+drivers/hwmon/ltc4282.c:ltc4282_parse_dt() {
+    ...
+        ret = device_property_read_u32(dev, "adi,current-limit-sense-microvolt",
+                                       &st->vsense_max);
+        if (!ret) {
+                int reg_val;
+
+                switch (val) {
+                case 12500:
+                        reg_val = 0;
+                        break;
+    ...
+}
+
+Because val holds a small integer representing vin_mode (from 0 to 3), it
+never matches any of the valid current limit cases.
+
+This causes it to always fall through to the default error case, return
+-EINVAL, and aborts probe initialization for any device tree using this
+property.
+
+Validate st->vsense_max instead to fix the problem.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index 0e7449db3158f..5f7ab813051c8 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -1425,7 +1425,7 @@ static int ltc4282_setup(struct ltc4282_state *st, struct device *dev)
+       if (!ret) {
+               int reg_val;
+-              switch (val) {
++              switch (st->vsense_max) {
+               case 12500:
+                       reg_val = 0;
+                       break;
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch b/queue-6.12/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
new file mode 100644 (file)
index 0000000..7c0d041
--- /dev/null
@@ -0,0 +1,57 @@
+From 6f15db240b39e6e8737de4011417ace1738f3885 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:48:42 +0800
+Subject: hwmon: (nzxt-smart2) Check return value of init_device() in probe
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit d533882ce1060866a590257f2c77ee23eabef5b8 ]
+
+The init_device() call in nzxt_smart2_hid_probe() can fail because it
+sends HID output reports to the hardware to detect fans and set the
+update interval.  If the hardware is not responding or the HID reports
+fail, init_device() returns a negative error code.
+
+However, the return value was ignored, causing the probe to continue
+and register an hwmon device even though the device was never properly
+initialized.  This leads to an inconsistent state where the driver
+reports stale data or blocks on wait queues that will never be woken.
+
+The same function's return value is already checked in the
+reset_resume() handler, confirming the author's intent that errors
+should be propagated.
+
+Note that this fix was not possible before commit 59d104b54b0b
+("hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop")
+because the out_hw_close error path was missing hid_device_io_stop(),
+which would have opened a use-after-free risk window.
+
+Fixes: 53e68c20aeb1 ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2.")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260804074842.505923-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/nzxt-smart2.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
+index 66c5886f411a6..8ff3ebc1bb4c1 100644
+--- a/drivers/hwmon/nzxt-smart2.c
++++ b/drivers/hwmon/nzxt-smart2.c
+@@ -760,7 +760,11 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
+       hid_device_io_start(hdev);
+-      init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      ret = init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      if (ret) {
++              dev_err(&hdev->dev, "init_device failed: %d\n", ret);
++              goto out_hw_close;
++      }
+       drvdata->hwmon =
+               hwmon_device_register_with_info(&hdev->dev, "nzxtsmart2", drvdata,
+-- 
+2.53.0
+
diff --git a/queue-6.12/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch b/queue-6.12/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
new file mode 100644 (file)
index 0000000..867fd10
--- /dev/null
@@ -0,0 +1,71 @@
+From 39949a72bea670fd17987e778cc779f802aad964 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 14:12:31 -0700
+Subject: hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 0dabe8a56f772f0ece46d2597799f412c277d874 ]
+
+In lm25066_probe(), the PMBus coefficients for current and power are
+scaled based on the shunt resistor value. The calculation evaluates the
+multiplication using 32-bit arithmetic because info->m is an int and
+shunt is a u32:
+
+static int lm25066_probe(struct i2c_client *client) {
+    ...
+    info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+    info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
+    ...
+}
+
+For large coefficients like 26882 (LM25056) or 15076 (LM5066i), a device
+tree shunt-resistor-micro-ohms value exceeding approximately 159,000
+(159 mOhm, which is physically valid for low-current applications) causes
+the intermediate product to exceed UINT_MAX (4,294,967,295). This results
+in a silent wraparound before the division by 1000.
+
+Furthermore, if the wrapped value has the most significant bit set,
+converting it back to the signed int info->m results in negative
+coefficients. This logic error leads to drastically corrupted current and
+power readings, which can cause erratic thermal or power management
+behavior in the system.
+
+Fix the problem by using 64-bit operations for the multiply/divide
+operations. This can still overflow, but only for unreasonably large
+shunt resistor values.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: 94ee5fcc240fe ("hwmon: (pmbus/lm25066) Support configurable sense resistor values")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index c36c124d1a2d8..f0bf3b1533313 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
++#include <linux/math.h>
+ #include <linux/of.h>
+ #include "pmbus.h"
+@@ -540,8 +541,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
+               shunt = 1000;
+-      info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+-      info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
++      info->m[PSC_CURRENT_IN] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_CURRENT_IN] * shunt, 1000);
++      info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_POWER] * shunt, 1000);
+ #if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)
+       /* LM25056 doesn't support OPERATION */
+-- 
+2.53.0
+
diff --git a/queue-6.12/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch b/queue-6.12/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
new file mode 100644 (file)
index 0000000..6928423
--- /dev/null
@@ -0,0 +1,259 @@
+From 25f23689466cbbb504002ef387913d04cfb9d09a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:05 +0300
+Subject: ipvs: avoid out-of-bounds write in ip_vs_nat_icmp
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 646922a0379496154e8c8faca4f8e2fd9100cacc ]
+
+Sashiko warns that local attacker can modify the packet
+while it is processed by IPVS. Some places read the
+IP ihl field multiple times which can cause out-of-bounds
+access. One such place is ip_vs_nat_icmp where we
+can write after the validated area.
+
+Fix it by providing ciph argument just like it is done for
+IPv6 and use ciph->len as offset to the embedded transport
+header.
+
+Modify some IPv4 header checks by reading the ihl field
+only once.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://sashiko.dev/#/patchset/20260722101517.36313-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h             |  2 +-
+ net/netfilter/ipvs/ip_vs_core.c | 67 +++++++++++++++++----------------
+ net/netfilter/ipvs/ip_vs_xmit.c |  2 +-
+ 3 files changed, 36 insertions(+), 35 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 6935ec09af24d..80110ec025002 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1707,7 +1707,7 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int dir, unsigned int toff,
+-                  bool has_ports);
++                  bool has_ports, struct ip_vs_iphdr *ciph);
+ #ifdef CONFIG_IP_VS_IPV6
+ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index 6207a91e93f3b..586346110cd89 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -747,28 +747,27 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
+  */
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int inout, unsigned int toff,
+-                  bool has_ports)
++                  bool has_ports, struct ip_vs_iphdr *ciph)
+ {
+       struct iphdr *iph        = ip_hdr(skb);
+       struct icmphdr *icmph    = (struct icmphdr *)(skb->data + toff);
+-      struct iphdr *ciph       = (struct iphdr *)(icmph + 1);
+-      unsigned int coff __maybe_unused = toff + sizeof(struct icmphdr);
++      struct iphdr *cih        = (struct iphdr *)(icmph + 1);
+       if (inout) {
+               iph->saddr = cp->vaddr.ip;
+               ip_send_check(iph);
+-              ciph->daddr = cp->vaddr.ip;
+-              ip_send_check(ciph);
++              cih->daddr = cp->vaddr.ip;
++              ip_send_check(cih);
+       } else {
+               iph->daddr = cp->daddr.ip;
+               ip_send_check(iph);
+-              ciph->saddr = cp->daddr.ip;
+-              ip_send_check(ciph);
++              cih->saddr = cp->daddr.ip;
++              ip_send_check(cih);
+       }
+       /* the TCP/UDP/SCTP port */
+       if (has_ports) {
+-              __be16 *ports = (void *)ciph + ciph->ihl*4;
++              __be16 *ports = (void *)(skb->data + ciph->len);
+               if (inout)
+                       ports[1] = cp->vport;
+@@ -782,10 +781,10 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       if (inout)
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered outgoing ICMP");
+       else
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered incoming ICMP");
+ }
+@@ -878,7 +877,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
+               ip_vs_nat_icmp_v6(skb, pp, cp, 1, toff, has_ports, ciph);
+       else
+ #endif
+-              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports);
++              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports, ciph);
+       if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
+               goto out;
+@@ -914,7 +913,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       struct ip_vs_iphdr ciph;
+       struct ip_vs_conn *cp;
+       struct ip_vs_protocol *pp;
+-      unsigned int offset, ihl;
++      unsigned int offset;
+       union nf_inet_addr snet;
+       *related = 1;
+@@ -927,7 +926,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+                       return NF_ACCEPT;
+       }
+-      ihl = ipvsh->len;
+       offset = ipvsh->len;
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
+@@ -953,11 +951,15 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      pp = ip_vs_proto_get(cih->protocol);
++      pp = ip_vs_proto_get(ciph.protocol);
+       if (!pp)
+               return NF_ACCEPT;
+@@ -968,8 +970,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking outgoing ICMP for");
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order */
+       cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
+                            ipvs, AF_INET, skb, &ciph);
+@@ -977,8 +977,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+               return NF_ACCEPT;
+       snet.ip = ipvsh->saddr.ip;
+-      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph, ihl,
+-                                  hooknum);
++      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph,
++                                  ipvsh->len, hooknum);
+ }
+ #ifdef CONFIG_IP_VS_IPV6
+@@ -1625,10 +1625,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!cih)
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      raddr = (union nf_inet_addr *)&cih->daddr;
+       hlen_ipip = cih->ihl * 4;
++      if (!(cih->version == 4 && hlen_ipip >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++      raddr = (union nf_inet_addr *)&cih->daddr;
+       /* Special case for errors for IPIP/UDP/GRE tunnel packets */
+       tunnel = false;
+@@ -1645,9 +1647,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+               if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP)
+                       return NF_ACCEPT;
+               offset += hlen_ipip;
+-              cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-              if (!(cih && cih->version == 4 && cih->ihl >= 5))
+-                      return NF_ACCEPT; /* The packet looks wrong, ignore */
+               tunnel = true;
+       } else if ((cih->protocol == IPPROTO_UDP ||     /* Can be UDP encap */
+                   cih->protocol == IPPROTO_GRE) &&    /* Can be GRE encap */
+@@ -1672,21 +1671,25 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+                       /* Skip IP and UDP/GRE tunnel headers */
+                       offset = offset2 + ulen;
+                       /* Now we should be at the original IP header */
+-                      cih = skb_header_pointer(skb, offset, sizeof(_ciph),
+-                                               &_ciph);
+-                      if (cih && cih->version == 4 && cih->ihl >= 5 &&
+-                          iproto == IPPROTO_IPIP)
++                      if (iproto == IPPROTO_IPIP)
+                               tunnel = true;
+                       else
+                               return NF_ACCEPT;
+               }
+       }
+-      pd = ip_vs_proto_data_get(ipvs, cih->protocol);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph))
++              return NF_ACCEPT;
++      pd = ip_vs_proto_data_get(ipvs, ciph.protocol);
+       if (!pd)
+               return NF_ACCEPT;
+       pp = pd->pp;
++      cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       /* Is the embedded protocol header present? */
+       if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
+               return NF_ACCEPT;
+@@ -1694,9 +1697,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking incoming ICMP for");
+-      offset2 = offset;
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order.
+        * For IPIP/UDP/GRE tunnel this is error for request, not for reply.
+        */
+@@ -1726,11 +1726,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       }
+       if (tunnel) {
+-              unsigned int hlen_orig = cih->ihl * 4;
++              unsigned int hlen_orig = ciph.len - ciph.off;
+               __be32 info = ic->un.gateway;
+               __u8 type = ic->type;
+               __u8 code = ic->code;
++              offset2 = offset;
+               /* Update the MTU */
+               if (ic->type == ICMP_DEST_UNREACH &&
+                   ic->code == ICMP_FRAG_NEEDED) {
+diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
+index b85420a3a14ce..240378e37741a 100644
+--- a/net/netfilter/ipvs/ip_vs_xmit.c
++++ b/net/netfilter/ipvs/ip_vs_xmit.c
+@@ -1577,7 +1577,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+       if (skb_cow(skb, rt->dst.dev->hard_header_len))
+               goto tx_error;
+-      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports);
++      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports, ciph);
+       /* Another hack: avoid icmp_send in ip_fragment */
+       skb->ignore_df = 1;
+-- 
+2.53.0
+
diff --git a/queue-6.12/ipvs-return-the-csum-validation-for-forward-hook.patch b/queue-6.12/ipvs-return-the-csum-validation-for-forward-hook.patch
new file mode 100644 (file)
index 0000000..20d8e84
--- /dev/null
@@ -0,0 +1,100 @@
+From 4a66052a6c966c86cc63f9e7658c5646f79b9408 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:06 +0300
+Subject: ipvs: return the csum validation for forward hook
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 99609cb0aa789c8d071050ce8579989551882cc6 ]
+
+Sashiko notes that playing games with the skb dst and rt
+flags instead of providing hooknum is not a good idea
+when validating the checksums.
+
+Also, skipping checksum validation for FORWARD packets
+risk silent data corruption, even if the only user is
+the FTP-CMD packets coming from the real server.
+
+Sashiko also noticed that by using common checksum
+helper in the previous commit we actually fixed old bug
+where the TCP/UDP checksum for IPv6 on CHECKSUM_COMPLETE
+was not validated correctly.
+
+Fixes: e876b75b9020 ("ipvs: fix the checksum validations")
+Link: https://sashiko.dev/#/patchset/20260722211420.153933-1-pablo%40netfilter.org
+Link: https://sashiko.dev/#/patchset/20260727185024.67534-1-ja%40ssi.bg
+Link: https://sashiko.dev/#/patchset/20260728202520.59179-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h                   | 19 +++++--------------
+ net/netfilter/ipvs/ip_vs_proto_sctp.c |  2 +-
+ 2 files changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 80110ec025002..1121845bcc2a6 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -24,9 +24,7 @@
+ #include <linux/netfilter.h>          /* for union nf_inet_addr */
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>                       /* for struct ipv6hdr */
+-#include <net/route.h>
+ #include <net/ipv6.h>
+-#include <net/ip6_fib.h>
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ #include <net/netfilter/nf_conntrack.h>
+ #endif
+@@ -1740,30 +1738,23 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+       return csum_partial(diff, sizeof(diff), oldsum);
+ }
+-static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
++static inline bool ip_vs_checksum_needed(struct sk_buff *skb)
+ {
+       /* Checksum unnecessary or already validated? */
+       if (skb_csum_unnecessary(skb))
+               return false;
+-      /* LOCAL_OUT ? */
+-      if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
++      /* Locally generated ? */
++      if (!skb->dev)
+               return false;
+-      /* !LOCAL_IN (FORWARD) ? */
+-      if (af == AF_INET6) {
+-              if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
+-                      return false;
+-      } else {
+-              if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+-                      return false;
+-      }
+       return true;
+ }
+ static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
+                                              int offset, int proto, int af)
+ {
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return true;
++      /* Validate csum even for FORWARD */
+       return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+index 3dbd3096e1637..c80567c73469b 100644
+--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+@@ -193,7 +193,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+       struct sctphdr *sh;
+       __le32 cmp, val;
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return 1;
+       sh = (struct sctphdr *)(skb->data + sctphoff);
+       cmp = sh->checksum;
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch b/queue-6.12/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
new file mode 100644 (file)
index 0000000..c5904de
--- /dev/null
@@ -0,0 +1,81 @@
+From 44eb5f3ba89966232a30ecde4bad6e59d7093c1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 13:15:08 +0000
+Subject: net/atm: fix slab-out-of-bounds read in vcc_setsockopt()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d0c80dbb970439bd2eeb0e5effff8c16a5f4e1e3 ]
+
+vcc_setsockopt() contained an ineffective optlen check:
+  if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+      return -EINVAL;
+
+If __SO_LEVEL_MATCH(optname, level) evaluated to false (e.g. if the caller
+passed a mismatched level), the length check optlen != __SO_SIZE(optname)
+was short-circuited and bypassed. Execution then fell through to switch(optname),
+calling copy_from_sockptr() assuming optval contained sufficient space.
+
+Furthermore, even if level matched, a cgroup BPF setsockopt filter could shrink
+optlen after entry. Because copy_from_sockptr() on kernel pointers uses memcpy(),
+this leads to a KASAN slab-out-of-bounds read when optlen is smaller than the
+expected structure size.
+
+Fix this by using copy_safe_from_sockptr(), which unconditionally validates
+that optlen is at least the expected size before copying. Also change the local
+'value' variable type from 'unsigned long' to 'int' so that SO_SETCLP matches
+its sizeof(int) ABI encoding on 64-bit systems.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+53ecc09fb81df10ef4de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=53ecc09fb81df10ef4de
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260805131508.3227331-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/atm/common.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/net/atm/common.c b/net/atm/common.c
+index 196c36269b34f..413863861bcaa 100644
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+                  sockptr_t optval, unsigned int optlen)
+ {
+       struct atm_vcc *vcc;
+-      unsigned long value;
++      int value;
+       int error;
+       if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+@@ -772,8 +772,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+       {
+               struct atm_qos qos;
+-              if (copy_from_sockptr(&qos, optval, sizeof(qos)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&qos, sizeof(qos), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               error = check_qos(&qos);
+               if (error)
+                       return error;
+@@ -786,8 +788,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+               return 0;
+       }
+       case SO_SETCLP:
+-              if (copy_from_sockptr(&value, optval, sizeof(value)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&value, sizeof(value), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               if (value)
+                       vcc->atm_options |= ATM_ATMOPT_CLP;
+               else
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-6.12/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..58b18e1
--- /dev/null
@@ -0,0 +1,42 @@
+From eef0796e2400996a278249697bd16f8f599919bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index 1a972b093a424..cc1d04d05e4b3 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1282,7 +1282,6 @@ static void hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-hns3-fix-speed-configuration-residue-after-drive.patch b/queue-6.12/net-hns3-fix-speed-configuration-residue-after-drive.patch
new file mode 100644 (file)
index 0000000..66d7f7f
--- /dev/null
@@ -0,0 +1,76 @@
+From be5615afc4cda920f79408139c9e104ad86183ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 17:30:36 +0800
+Subject: net: hns3: fix speed configuration residue after driver reload
+
+From: Jijie Shao <shaojijie@huawei.com>
+
+[ Upstream commit 3860d8748af315bfee6fe669fddc1fc17d3214db ]
+
+After setting a 100G optical port to 40G via ethtool and reloading
+the driver, the port remains at 40G instead of reverting to the
+firmware default speed of 100G.
+
+The commit referenced in Fixes: added two overwrites in
+hclge_init_ae_dev() for non-copper media, so that optical ports
+connected to forced-mode remotes inherit the firmware-preset
+autoneg and speed instead of the hardcoded defaults:
+
+  req_autoneg = mac.autoneg
+  req_speed   = mac.speed         (when autoneg disabled)
+
+The autoneg overwrite keeps existing behavior:
+hclge_set_autoneg_speed_dup() already uses mac.autoneg (not
+req_autoneg) since it was introduced, so autoneg inheritance from
+firmware was already in place. This part is kept.
+
+The speed overwrite, however, introduces the residue: mac.speed
+reflects whatever was last programmed into the MAC, and after unload
+firmware does not restore the MAC speed to the flash default. So if
+the user changed speed via ethtool in a prior load, mac.speed still
+carries that value on reload and req_speed inherits it.
+
+Fix by dropping the req_speed overwrite only. req_speed keeps the
+firmware default value set in hclge_configure() (cfg.default_speed),
+so a reload reverts the speed to default, matching the expectation
+that a driver reload resets link configuration.
+
+Trade-off: on optical ports whose firmware default speed does not
+match a forced-mode remote, reload now drops the link and the user
+must re-apply ethtool configuration. This is acceptable: a driver
+reload is expected to reset link configuration, not to inherit
+runtime state from before unload. The autoneg inheritance is left
+in place as established behavior; changing it is out of scope for
+this patch and would itself be a user-perceivable behavior change.
+
+Fixes: d9d349c4e8a0 ("net: hns3: differentiate autoneg default values between copper and fiber")
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260724093036.426631-1-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 79858b06c97b0..786aefc3d107e 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -11930,12 +11930,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+       if (ret)
+               goto err_ptp_uninit;
+-      if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER) {
++      if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER)
+               hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg;
+-              if (hdev->hw.mac.autoneg == AUTONEG_DISABLE &&
+-                  hdev->hw.mac.speed != SPEED_UNKNOWN)
+-                      hdev->hw.mac.req_speed = hdev->hw.mac.speed;
+-      }
+       ret = hclge_set_autoneg_speed_dup(hdev);
+       if (ret) {
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-6.12/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..85576ee
--- /dev/null
@@ -0,0 +1,134 @@
+From 12ee39e1d8741dace9c1b2257a088e0d8630a378 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 0b82a6a133d6c..74f68b70ad1c1 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1025,13 +1025,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1073,7 +1071,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1084,7 +1082,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       if (!tracer->str_db.loaded)
+@@ -1134,7 +1132,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mutex_lock(&tracer->state_lock);
+@@ -1163,7 +1161,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1215,7 +1213,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch b/queue-6.12/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
new file mode 100644 (file)
index 0000000..6231b47
--- /dev/null
@@ -0,0 +1,100 @@
+From d40cda53d7f3115b37b88f7d65037f3964c806ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 07:43:38 +0300
+Subject: net/mlx5e: TC, Check if flow is PEER before acquiring devcom lock
+
+From: Shay Drory <shayd@nvidia.com>
+
+[ Upstream commit 6ddfba2ea98db21b001e0e5c472499156224650c ]
+
+In case __mlx5e_add_fdb_flow() fails in lower levels, the flow is
+deleted via mlx5e_tc_del_flow(), and mlx5e_tc_del_flow() is acquiring
+ESW devcom lock without condition. In addition, in case of peer_flow,
+__mlx5e_add_fdb_flow() is called while holding ESW devcom comp lock.
+This results in an AA deadlock.
+
+To fix this, introduce a new PEER flag that is set on flows created as
+peer flows (the duplicate flows on peer devices), and check it in
+mlx5e_tc_del_flow() before acquiring ESW devcom lock.
+
+Lockdep splat:
+============================================
+WARNING: possible recursive locking detected
+============================================
+ Possible unsafe locking scenario:
+       CPU0
+       ----
+  lock(&comp->lock_key#2);
+  lock(&comp->lock_key#2);
+ *** DEADLOCK ***
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x69/0xa0
+ print_deadlock_bug.cold+0xbd/0xca
+ __lock_acquire+0x1671/0x2ec0
+ lock_acquire+0x10e/0x2e0
+ down_read+0x95/0x430
+ mlx5_devcom_for_each_peer_begin+0x4e/0xe0 [mlx5_core]
+ mlx5e_tc_del_flow+0x11d/0xa70 [mlx5_core]
+ mlx5e_flow_put+0x99/0x100 [mlx5_core]
+ __mlx5e_add_fdb_flow+0x409/0xf00 [mlx5_core]
+ mlx5e_configure_flower+0x2a86/0x4100 [mlx5_core]
+ mlx5e_rep_setup_tc_cls_flower+0x12f/0x1b0 [mlx5_core]
+ mlx5e_rep_setup_tc_cb+0x153/0x750 [mlx5_core]
+ tc_setup_cb_add+0x1dc/0x470
+ fl_change+0x2f4d/0x626d [cls_flower]
+ tc_new_tfilter+0x79b/0x2310
+ rtnetlink_rcv_msg+0x778/0xad0
+ do_syscall_64+0x70/0x960
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ </TASK>
+
+Fixes: 04de7dda7394 ("net/mlx5e: Infrastructure for duplicated offloading of TC flows")
+Signed-off-by: Shay Drory <shayd@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260728044338.2271143-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h | 1 +
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c      | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+index efb34de4cb7ad..692ac2f21d94e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+@@ -30,6 +30,7 @@ enum {
+       MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 9,
+       MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 10,
+       MLX5E_TC_FLOW_FLAG_USE_ACT_STATS         = MLX5E_TC_FLOW_BASE + 11,
++      MLX5E_TC_FLOW_FLAG_PEER                  = MLX5E_TC_FLOW_BASE + 12,
+ };
+ struct mlx5e_tc_flow_parse_attr {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 8878990254f46..a5ae179310672 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -2161,7 +2161,8 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
+       if (mlx5e_is_eswitch_flow(flow)) {
+               struct mlx5_devcom_comp_dev *devcom = flow->priv->mdev->priv.eswitch->devcom;
+-              if (!mlx5_devcom_for_each_peer_begin(devcom)) {
++              if (flow_flag_test(flow, PEER) ||
++                  !mlx5_devcom_for_each_peer_begin(devcom)) {
+                       mlx5e_tc_del_fdb_flow(priv, flow);
+                       return;
+               }
+@@ -4605,6 +4606,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
+       else
+               in_mdev = priv->mdev;
++      flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_PEER);
+       parse_attr = flow->attr->parse_attr;
+       peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
+                                        parse_attr->filter_dev,
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-6.12/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..ccd5534
--- /dev/null
@@ -0,0 +1,60 @@
+From bbba96b65172c59c4b73969d8187ee32555a118e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index 2f872d064396d..8cc538358f6a3 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-6.12/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..491e394
--- /dev/null
@@ -0,0 +1,78 @@
+From f8b4f08db0c680fbc67b7b4209c6f507f8da3da5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index b80bd3a907739..52e261ce91e8e 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -893,8 +893,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -914,8 +912,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -930,6 +926,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-prestera-validate-firmware-header-length.patch b/queue-6.12/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..80a0dad
--- /dev/null
@@ -0,0 +1,42 @@
+From a9f480441ad7481fbf3775bb5d66002f7b5fcdce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index 35857dc19542f..5db2c9e5e077d 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -684,6 +684,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-6.12/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..51fd571
--- /dev/null
@@ -0,0 +1,45 @@
+From 36425ae87025956c1a7d109e6208592bf701706a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 4a09e780406fe..e8b03cf3a428c 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -773,7 +773,6 @@ bool sk_mc_loop(const struct sock *sk)
+               return inet6_test_bit(MC6_LOOP, sk);
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch b/queue-6.12/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
new file mode 100644 (file)
index 0000000..ef7cc2c
--- /dev/null
@@ -0,0 +1,116 @@
+From 64e91994f52a60753479ee4dea674bc7b5755d51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 08:56:32 -0400
+Subject: net/sched: cls_api: Always acquire rtnl_lock when destroying locked
+ classifiers
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit a347304b2ca1a5377d5bd2d8a72e4b4f12afe648 ]
+
+Another challenge with unlocked filters.
+There is a short window in tc_new_tfilter where a tcf_proto can be found
+and briefly referenced by a totally unrelated, unlocked classifier's request
+and cause a race.
+
+Feng created a poc which created this race with two threads, one creating a
+u32 filter and other a flower filter in the same chain/prio:
+
+1. Both threads enter tc_new_tfilter, both find the chain empty, both
+   drop filter_chain_lock
+2. u32 finishes tcf_proto_create("u32") first, calls
+   tcf_chain_tp_insert_unique() -> inserts u32_tp into the chain
+3. flower finishes tcf_proto_create("flower") later, calls
+   tcf_chain_tp_insert_unique() -> tcf_chain_tp_find() now sees u32_tp
+   already there, takes a reference on it, destroys flower's own tp_new
+   and returns u32_tp to the caller.
+
+Flower then hits the kind mismatch check (because it requested for kind
+"flower" but tp->ops->kind is "u32") and goes through the errout path
+which calls tcf_proto_put() on u32_tp. If the u32 thread has already
+gone through its own errout (its change() call failed on the PoC's empty
+options) and dropped its create and insert refs, flower's put is the
+last one and drops u32_tp's refcnt to zero.
+
+At this point tp->ops->destroy() runs in a context that never took
+rtnl_lock. When that happens, it might cause a UAF like the following
+(illustrated by the PoC):
+
+[  +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
+[  +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524
+
+  Call Trace:
+   u32_init (net/sched/cls_u32.c:393)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Allocated by task 526:
+   u32_init (net/sched/cls_u32.c:378)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Freed by task 522:
+   kfree
+   u32_destroy (net/sched/cls_u32.c:662)
+   tcf_proto_destroy (net/sched/cls_api.c:446)
+   tcf_proto_put (net/sched/cls_api.c:459)
+   tc_new_tfilter (net/sched/cls_api.c:2459)
+
+Fix this by having tcf_proto_destroy() take rtnl_lock around
+tp->ops->destroy() for locked classifiers whenever rtnl is not held.
+
+To explain why I used a temp variable "not_lockless" I'd like to point to a
+semi-related note on rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (adding here
+for future cleanup if deemed necessary):
+The rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are
+redundant sources of truth for whether rtnl_lock is held. Among the nine
+classifier destroy(..rtnl_held..) callbacks, only flower consults the
+rtnl_held parameter which it propagates to tc_setup_cb_destroy()
+and tc_setup_cb_call(). The other eight (u32, flow, bpf, cgroup, route, basic,
+fw, mall) ignore it entirely;-> those that call tc_setup_cb_destroy()
+(u32, bpf, mall) hardcode true always instead of forwarding the parameter.
+
+A future cleanup should remove the rtnl_held parameter from the destroy callback
+signature entirely and have callers rely solely on their knowledge whether
+they are running in an unlocked context.
+
+Fixes: 12db03b65c2b ("net: sched: extend proto ops to support unlocked classifiers")
+Reported-by: Feng Xue <feng.xue@outlook.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260801125632.360365-1-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_api.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index c5aeff709ca66..51a09d5553102 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -443,7 +443,22 @@ static void tcf_chain_put(struct tcf_chain *chain);
+ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
+                             bool sig_destroy, struct netlink_ext_ack *extack)
+ {
+-      tp->ops->destroy(tp, rtnl_held, extack);
++      /* A locked classifier's destroy callback (e.g. u32_destroy) uses
++       * rtnl_dereference() and mutates shared structures (e.g. the
++       * tc_u_common hash list) that are only safe under rtnl_lock. When an
++       * unlocked classifier's request (e.g. flower on ingress) loses the
++       * tcf_chain_tp_insert_unique() race and ends up dropping the last
++       * reference on a locked classifier's proto, destroy() would run
++       * without rtnl held. Take it here in that case.
++       */
++      bool not_lockless = !rtnl_held &&
++              !(tp->ops->flags & TCF_PROTO_OPS_DOIT_UNLOCKED);
++
++      if (not_lockless)
++              rtnl_lock();
++      tp->ops->destroy(tp, rtnl_held || not_lockless, extack);
++      if (not_lockless)
++              rtnl_unlock();
+       tcf_proto_count_usesw(tp, false);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-6.12/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..8029498
--- /dev/null
@@ -0,0 +1,142 @@
+From 838c70142b181c6adb74f7939a48fa49b5b8d156 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index b9c58c040c305..38469cdcb22d6 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -52,6 +52,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -66,9 +67,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -81,9 +84,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -297,6 +302,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -307,6 +319,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -334,11 +351,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -558,7 +575,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-6.12/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..eda526a
--- /dev/null
@@ -0,0 +1,50 @@
+From 8355e9ad33518ce0b79c83b05c20e23d357587ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index 2f33739036bb1..43908ec231696 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1265,7 +1265,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ntohs(ipv6h_check->payload_len);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-6.12/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..76810bb
--- /dev/null
@@ -0,0 +1,57 @@
+From 0427380ab1515e4e31419c3cf965c2b5a51bb4f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index 018ce8133b026..149d63cff667e 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1918,7 +1918,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch b/queue-6.12/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
new file mode 100644 (file)
index 0000000..94a4b15
--- /dev/null
@@ -0,0 +1,71 @@
+From 2d9d7284200dfa2b9a76e8a092c9b575255ccffb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 09:07:01 +0200
+Subject: net/smc: fix TOCTOU race between smc_listen_out() and listener close
+
+From: Sidraya Jayagond <sidraya@linux.ibm.com>
+
+[ Upstream commit 185a4caeecabc150106deda1da170b09f2ad803f ]
+
+smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
+then acquires lock_sock_nested() only after the check passes. This
+opens a window where smc_close_active() can transition the listener
+to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
+queue, and release the lock, all between the lockless read and the
+delayed lock acquisition:
+
+  smc_listen_work (smc_hs_wq)          smc_close_active()
+  -------------------------------      -------------------------
+  release_sock(child)
+  if (sk_state == SMC_LISTEN) TRUE
+                                        lock_sock(listener)
+                                        sk_state = SMC_CLOSED
+                                        smc_close_cleanup_listen()
+                                        release_sock(listener)
+                                        flush_work(tcp_listen_work)
+  lock_sock_nested(listener)
+  smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
+
+smc_close_active() flushes only tcp_listen_work. Work items already
+dispatched onto smc_hs_wq for the CLC handshake continue running
+unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
+is never released, so the child smc_sock, its clcsock, and the
+reference all leak. A remote peer that opens TCP connections while the
+server calls close() can exhaust kernel memory.
+
+Move lock_sock_nested() to before the sk_state check so that the test
+and the enqueue are atomic under the listener lock.
+
+Fixes: fd57770dd198 ("net/smc: wait for pending work before clcsock release_sock")
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260803070701.126339-1-sidraya@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 8d740f588a771..8e95839161aa1 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1933,11 +1933,12 @@ static void smc_listen_out(struct smc_sock *new_smc)
+               atomic_dec(&lsmc->queued_smc_hs);
+       release_sock(newsmcsk); /* lock in smc_listen_work() */
++      lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+       if (lsmc->sk.sk_state == SMC_LISTEN) {
+-              lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+               smc_accept_enqueue(&lsmc->sk, newsmcsk);
+               release_sock(&lsmc->sk);
+       } else { /* no longer listening */
++              release_sock(&lsmc->sk);
+               smc_close_non_accepted(newsmcsk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch b/queue-6.12/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
new file mode 100644 (file)
index 0000000..9b8b37f
--- /dev/null
@@ -0,0 +1,117 @@
+From f835e31bec55bd97eec618d3f5d7b51115e218b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:38:50 +0000
+Subject: net: thunderbolt: Tear down DMA paths before stopping the rings
+
+From: Fan XinRan <shinjiangjiang@gmail.com>
+
+[ Upstream commit 68bf02b6b4ad3f748c6db71fd77b6c0402d252f4 ]
+
+tbnet_tear_down() stops both rings and frees their frame buffers before
+calling tb_xdomain_disable_paths().  tb_ring_stop() zeroes the ring's
+descriptor base and tbnet_free_buffers() unmaps and frees the pages the
+frames sit in, so by the time __tb_path_deactivate_hop() polls the hop's
+'pending' bit, anything still in flight has nowhere to drain to.
+
+The teardown sequence has been in this order since the driver was added.
+The setup path has not: commit ff7cd07f3064 ("net: thunderbolt: Enable
+DMA paths only after rings are enabled") moved the path enable to the end
+of tbnet_connected_work() and documented why:
+
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
+        */
+
+Teardown was never updated to match, so the rings and the paths now come
+down in the same order they go up instead of in reverse.
+
+On an ASMedia ASM4242 host router the 'pending' bit then never clears:
+every teardown burns the full 500 ms timeout and
+__tb_path_deactivate_hop() returns -ETIMEDOUT.  Raising the timeout to
+5 s does not help, so the hop is not slow to drain, it never drains
+at all.
+
+The failure is invisible above the thunderbolt core.
+__tb_path_deactivate_hops() is void and only calls tb_port_warn();
+tb_path_deactivate(), tb_tunnel_deactivate() and
+__tb_disconnect_xdomain_paths() are void as well, and
+tb_disconnect_xdomain_paths() ends in an unconditional "return 0".  So
+tb_xdomain_disable_paths() reports success and the netdev_warn() below
+it never fires.  Repeated teardowns eventually take the XDomain control
+channel down, after which the peer node is gone and only a power cycle
+brings the controller back.
+
+Deactivating the paths first fixes it.  Measured with kretprobes on a
+stock v6.17 tree with no other patches applied, on a link that was up
+and had just carried traffic:
+
+  before: __tb_path_deactivate_hop() returns 0 for the first hop, then
+          -ETIMEDOUT for the second 500335 us later
+  after:  0 for both, 525 us apart
+
+Alternating the two orderings ABBA over three load levels, four
+teardowns per arm: every teardown failed before the change (21 of 21
+that ran), none failed after (0 of 24).  The before arms ran short
+because the link died partway through.  The same split shows up when
+the interface is enslaved to a bond instead of just brought down, which
+is how I ran into this in the first place.  Throughput and latency after
+the change are unchanged.
+
+Hosts whose routers drain the hop despite the stale descriptor base see
+no functional difference, since the paths end up deactivated either way.
+
+Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
+Signed-off-by: Fan XinRan <shinjiangjiang@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260803-b4-tbnet-teardown-v2-1-27de6a13ca2d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 960839a651e51..ceaba08cd378a 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -389,11 +389,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+                               break;
+               }
+-              tb_ring_stop(net->rx_ring.ring);
+-              tb_ring_stop(net->tx_ring.ring);
+-              tbnet_free_buffers(&net->rx_ring);
+-              tbnet_free_buffers(&net->tx_ring);
+-
++              /* Tear the paths down before stopping the rings.  This mirrors
++               * tbnet_connected_work(), which enables the paths last so the
++               * Rx ring is primed before packets can arrive.  Stopping a
++               * ring zeroes its descriptor base and tbnet_free_buffers()
++               * unmaps and frees the frame buffers, leaving anything still
++               * in flight with nowhere to drain to;
++               * __tb_path_deactivate_hop() then waits for the hop's
++               * 'pending' bit, which on some host routers never clears in
++               * that state.
++               */
+               ret = tb_xdomain_disable_paths(net->xd,
+                                              net->local_transmit_path,
+                                              net->tx_ring.ring->hop,
+@@ -402,6 +407,11 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+               if (ret)
+                       netdev_warn(net->dev, "failed to disable DMA paths\n");
++              tb_ring_stop(net->rx_ring.ring);
++              tb_ring_stop(net->tx_ring.ring);
++              tbnet_free_buffers(&net->rx_ring);
++              tbnet_free_buffers(&net->tx_ring);
++
+               tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+               net->remote_transmit_path = 0;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.12/netfilter-ipset-switch-ext_size-to-atomic64_t.patch b/queue-6.12/netfilter-ipset-switch-ext_size-to-atomic64_t.patch
new file mode 100644 (file)
index 0000000..78cb332
--- /dev/null
@@ -0,0 +1,134 @@
+From e150589a970d2808d2190209e0c52aee3a7696b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 20:38:50 +0200
+Subject: netfilter: ipset: switch ext_size to atomic64_t
+
+From: Jozsef Kadlecsik <kadlec@netfilter.org>
+
+[ Upstream commit 712a6f545c359b427daa9a5a782e30d2f8331e25 ]
+
+The hash types do not acquire set->lock, they use 'region locking' where
+only part of the hash table is locked. Parallel inserts and deletes are
+possible and CPUs can race on ->ext_size update.  Switch to atomic64_t.
+
+This leaves another bug unresolved: there still can be a race on
+comment extension re-init.  This will be handled in a later commit
+when converting to rhashtable backend.
+
+Fixes: f66ee0410b1c ("netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports")
+Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netfilter/ipset/ip_set.h  | 2 +-
+ net/netfilter/ipset/ip_set_bitmap_gen.h | 4 ++--
+ net/netfilter/ipset/ip_set_core.c       | 6 +++---
+ net/netfilter/ipset/ip_set_hash_gen.h   | 2 +-
+ net/netfilter/ipset/ip_set_list_set.c   | 4 ++--
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
+index b98331572ad29..cadae9b2578f1 100644
+--- a/include/linux/netfilter/ipset/ip_set.h
++++ b/include/linux/netfilter/ipset/ip_set.h
+@@ -273,7 +273,7 @@ struct ip_set {
+       /* Number of elements (vs timeout) */
+       u32 elements;
+       /* Size of the dynamic extensions (vs timeout) */
+-      size_t ext_size;
++      atomic64_t ext_size;
+       /* Element data size */
+       size_t dsize;
+       /* Offsets to extensions in elements */
+diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
+index cb48a2b9cb9fd..cf8468bf987db 100644
+--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
++++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
+@@ -77,7 +77,7 @@ mtype_flush(struct ip_set *set)
+               mtype_ext_cleanup(set);
+       bitmap_zero(map->members, map->elements);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ /* Calculate the actual memory size of the set data */
+@@ -93,7 +93,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct mtype *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = mtype_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index f51a1af31513c..29bf5ee74fe36 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -350,7 +350,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       size_t len = ext->comment ? strlen(ext->comment) : 0;
+       if (unlikely(c)) {
+-              set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++              atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+               rcu_assign_pointer(comment->c, NULL);
+               kfree_rcu(c, rcu);
+       }
+@@ -362,7 +362,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       if (unlikely(!c))
+               return;
+       strscpy(c->str, ext->comment, len + 1);
+-      set->ext_size += sizeof(*c) + strlen(c->str) + 1;
++      atomic64_add(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, c);
+ }
+ EXPORT_SYMBOL_GPL(ip_set_init_comment);
+@@ -392,7 +392,7 @@ ip_set_comment_free(struct ip_set *set, void *ptr)
+       c = rcu_dereference_protected(comment->c, 1);
+       if (unlikely(!c))
+               return;
+-      set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++      atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, NULL);
+       kfree_rcu(c, rcu);
+ }
+diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
+index 4c1082e38e3d1..81d7f601ed06a 100644
+--- a/net/netfilter/ipset/ip_set_hash_gen.h
++++ b/net/netfilter/ipset/ip_set_hash_gen.h
+@@ -1289,7 +1289,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+-      memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
++      memsize = mtype_ahash_memsize(h, t) + ext_size + atomic64_read(&set->ext_size);
+       htable_bits = t->htable_bits;
+       rcu_read_unlock_bh();
+diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
+index 83e1fdcc752d6..9d6ab69ca1a37 100644
+--- a/net/netfilter/ipset/ip_set_list_set.c
++++ b/net/netfilter/ipset/ip_set_list_set.c
+@@ -421,7 +421,7 @@ list_set_flush(struct ip_set *set)
+       list_for_each_entry_safe(e, n, &map->members, list)
+               list_set_del(set, e);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ static void
+@@ -455,7 +455,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct list_set *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = list_set_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = list_set_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+-- 
+2.53.0
+
diff --git a/queue-6.12/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-6.12/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..9ed75fe
--- /dev/null
@@ -0,0 +1,50 @@
+From 5f96b7d574fd9c09b49512dd098211ef3aeb436b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 840789e182ef3..facd4e28770be 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10585,6 +10585,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10626,6 +10627,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-6.12/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch b/queue-6.12/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch
new file mode 100644 (file)
index 0000000..bc05bd3
--- /dev/null
@@ -0,0 +1,54 @@
+From b448d20c7ea930a4ab80846136ccfbfad91b6db7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 17:00:30 +0000
+Subject: pds_core: cancel pending PCI reset work on AER recovery
+
+From: Nikhil P. Rao <nikhil.rao@amd.com>
+
+[ Upstream commit 57d635329d799b79096155cdf47ee0013d6780d1 ]
+
+pdsc_check_pci_health() queues pci_reset_work when it sees a broken PCI
+connection, and nothing cancels it. When the PCI core starts AER
+recovery, pdsc_pci_error_detected() runs pdsc_reset_prepare() and
+recovers the device, but a pci_reset_work queued just before is left
+pending. If it runs after recovery released the device lock, it resets a
+device the driver now considers healthy, bouncing the link for no reason.
+
+Cancel pci_reset_work in pdsc_pci_error_detected() after
+pdsc_reset_prepare(), which has already stopped the health thread so it
+cannot requeue the work. cancel_work_sync() is safe under the device
+lock here because pdsc_pci_reset_thread() uses pci_try_reset_function(),
+which returns instead of blocking on the lock. Only PFs initialize
+pci_reset_work, so guard the cancel with !is_virtfn.
+
+Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread")
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260714180223.1642792-2-nikhil.rao%40amd.com?part=1
+Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260727170030.361116-1-nikhil.rao@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pds_core/main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index 2329396ec3e25..9526223a72978 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -550,7 +550,11 @@ static pci_ers_result_t pdsc_pci_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t error)
+ {
+       if (error == pci_channel_io_frozen) {
++              struct pdsc *pdsc = pci_get_drvdata(pdev);
++
+               pdsc_reset_prepare(pdev);
++              if (!pdev->is_virtfn)
++                      cancel_work_sync(&pdsc->pci_reset_work);
+               return PCI_ERS_RESULT_NEED_RESET;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.12/pds_core-keep-the-health-thread-stopped-during-reset.patch b/queue-6.12/pds_core-keep-the-health-thread-stopped-during-reset.patch
new file mode 100644 (file)
index 0000000..0fa90de
--- /dev/null
@@ -0,0 +1,87 @@
+From d7214c5db97de33d0312a0657fefd5e0352ccc6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 16:45:48 +0000
+Subject: pds_core: keep the health thread stopped during reset
+
+From: Nikhil P. Rao <nikhil.rao@amd.com>
+
+[ Upstream commit cd09971dcc1c499ae0879010a00e9dba87abdc4f ]
+
+Commit d9407ff11809 ("pds_core: Prevent health thread from running
+during reset/remove") stops the health thread with cancel_work_sync()
+before a reset, but a devcmd timeout during pdsc_fw_down() re-queues
+health_work, so pdsc_health_thread() runs again mid-reset and double
+allocates the core DMA queues via pdsc_fw_up().
+
+Only the reset path is affected: on remove PDSC_S_STOPPING_DRIVER gates
+the health thread and the workqueue is destroyed.
+
+Use disable_work_sync() to cancel health_work and block further
+queue_work() on it, and enable_work() in pdsc_restart_health_thread() to
+re-allow it after the reset.
+
+disable_work_sync() keeps a disable depth, so every disable must be
+matched by one enable. pdsc_reset_prepare() stops the health thread and
+pdsc_reset_done() restarts it. On the AER path pdsc_pci_error_detected()
+calls pdsc_reset_prepare(), then pdsc_pci_error_resume() re-inits via
+pci_reset_function_locked() (pds_core has no .slot_reset handler), which
+runs the pair again - stopping the thread twice but restarting it once.
+Gate the disable and enable on a health_stopped flag so each fires at
+most once per stopped/running transition.
+
+Fixes: d9407ff11809 ("pds_core: Prevent health thread from running during reset/remove")
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2
+Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260727164548.359562-1-nikhil.rao@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pds_core/core.h |  1 +
+ drivers/net/ethernet/amd/pds_core/main.c | 10 ++++++++--
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h
+index becd3104473c2..4dbfe2373b3ac 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.h
++++ b/drivers/net/ethernet/amd/pds_core/core.h
+@@ -170,6 +170,7 @@ struct pdsc {
+       struct timer_list wdtimer;
+       unsigned int wdtimer_period;
+       struct work_struct health_work;
++      bool health_stopped;
+       struct devlink_health_reporter *fw_reporter;
+       u32 fw_recoveries;
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index c78b17d230a84..2329396ec3e25 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -464,8 +464,10 @@ static void pdsc_stop_health_thread(struct pdsc *pdsc)
+               return;
+       timer_shutdown_sync(&pdsc->wdtimer);
+-      if (pdsc->health_work.func)
+-              cancel_work_sync(&pdsc->health_work);
++      if (pdsc->health_work.func && !pdsc->health_stopped) {
++              disable_work_sync(&pdsc->health_work);
++              pdsc->health_stopped = true;
++      }
+ }
+ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+@@ -473,6 +475,10 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+       if (pdsc->pdev->is_virtfn)
+               return;
++      if (pdsc->health_stopped) {
++              enable_work(&pdsc->health_work);
++              pdsc->health_stopped = false;
++      }
+       timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
+       mod_timer(&pdsc->wdtimer, jiffies + 1);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch b/queue-6.12/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
new file mode 100644 (file)
index 0000000..09ec81e
--- /dev/null
@@ -0,0 +1,104 @@
+From c20093e513b188043cfddb54cf1b19c7f46c5167 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 12:29:48 +0000
+Subject: Revert "net: thunderbolt: Enable end-to-end flow control also in
+ transmit"
+
+From: Fan Ye <fy15309206903@gmail.com>
+
+[ Upstream commit 1881f2efbf7f78dc0a79a387b29fde6ff56d3731 ]
+
+This reverts commit a8065af3346ebd7c76ebc113451fb3ba94cf7769.
+
+Per the USB4 spec, a Transmit Descriptor Ring with E2E flow control
+disabled does not require any credits to be available before the Host
+Interface Adapter Layer transmits a tunneled packet from it. Once E2E is
+enabled on that ring the controller must first obtain end-to-end
+credits.
+
+The ASMedia ASM4242 USB4 host router (PCI 1b21:2425) never delivers
+those credits. The controller does accept the configuration: reading the
+ring OPTIONS register back right after tb_ring_start() returns exactly
+what was written, including RING_FLAG_E2E_FLOW_CONTROL (bit 28) and the
+E2E HopID field. No credit ever arrives though, so the Tx ring's
+hardware consumer index never advances and the link carries no traffic
+at all.
+
+Measured on two hosts connected point to point, onboard ASM4242 on MSI
+X870E and X870, v6.17, stock drivers/net/thunderbolt/main.c with only
+this revert applied on top:
+
+  before: 100% packet loss to the peer; thunderbolt0 is up and the
+          XDomain handshake completes ("new host found"), but iperf3
+          fails with "No route to host" once the neighbour entry
+          expires
+  after:  0% packet loss, 0.28 ms RTT; iperf3 4.21 Gb/s one way and
+          5.17 Gb/s the other (5 runs each, stddev <= 0.02), 1
+          retransmit in 10 s
+
+An instrumented build additionally showed a frozen-Tx-consumer watchdog
+firing ~30k times in a 10 s window before this change.
+
+Rx-side E2E is not touched by this revert, so peers that do return
+credits keep receive-side flow control.
+
+ASMedia does not look like an isolated case. The out-of-tree
+thunderbolt-ibverbs project disables native E2E on AMD NHI by default,
+noting that "Strix Halo has reproduced TX completion wedges with
+multiple native E2E rings active" -- the same failure mode, on a
+different vendor. Since the driver has no way to tell in advance which
+host router returns the credits, going back to the previous behaviour
+looks safer than adding a quirk per affected part; Tx-side E2E can be
+reintroduced as an opt-in for controllers that are known to implement
+the credit return.
+
+Note that the reverted commit was not fixing a reported problem, it was
+derived from the spec wording alone, so this revert is not expected to
+regress a known workload. Cc'ing the original author in case there was
+one.
+
+Fixes: a8065af3346e ("net: thunderbolt: Enable end-to-end flow control also in transmit")
+Cc: zhangjianrong <zhangjianrong5@huawei.com>
+Signed-off-by: Fan Ye <fy15309206903@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260727123002.25225-1-fy15309206903@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 5d7d11d75b0b8..960839a651e51 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -928,12 +928,8 @@ static int tbnet_open(struct net_device *dev)
+       netif_carrier_off(dev);
+-      flags = RING_FLAG_FRAME;
+-      /* Only enable full E2E if the other end supports it too */
+-      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
+-              flags |= RING_FLAG_E2E;
+-
+-      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags);
++      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE,
++                              RING_FLAG_FRAME);
+       if (!ring) {
+               netdev_err(dev, "failed to allocate Tx ring\n");
+               return -ENOMEM;
+@@ -952,6 +948,11 @@ static int tbnet_open(struct net_device *dev)
+       sof_mask = BIT(TBIP_PDF_FRAME_START);
+       eof_mask = BIT(TBIP_PDF_FRAME_END);
++      flags = RING_FLAG_FRAME;
++      /* Only enable full E2E if the other end supports it too */
++      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
++              flags |= RING_FLAG_E2E;
++
+       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags,
+                               net->tx_ring.ring->hop, sof_mask,
+                               eof_mask, tbnet_start_poll, net);
+-- 
+2.53.0
+
diff --git a/queue-6.12/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-6.12/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..0ed9c53
--- /dev/null
@@ -0,0 +1,54 @@
+From 518cad2e31e88bf9af01a051848b761626d77be6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 44f06c5f1f256..ebdc48be47813 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -573,6 +573,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-6.12/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-6.12/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..8f44e0b
--- /dev/null
@@ -0,0 +1,57 @@
+From cdcadca44dbfabc328f32087de184c92f166c53b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 27a7739a7d424..b6eb79ef6a55d 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3354,12 +3354,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-6.12/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch b/queue-6.12/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
new file mode 100644 (file)
index 0000000..8da8271
--- /dev/null
@@ -0,0 +1,88 @@
+From ef4fb802705b6b0b3209e543dd57b40010a1fb40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 21:46:35 +0200
+Subject: selftests/ftrace: refactor eprobes test to fix argument checks
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+[ Upstream commit 6e3abef2a27e7402a94111c9eff85d887e64a309 ]
+
+The add/remove eprobe test installs an eprobe for the openat syscall and
+runs ls. It checks the filenames that were opened by ls against a
+whitelist and a blacklist.
+
+Commit 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING
+pointer") fixed access to some string fields in eprobes. This triggers
+test failures as the blacklist does not allow relative paths for the
+openat parameters.
+
+What makes this test unstable is the fact that the openat calls vary a
+lot between different systems.
+
+Refactor the test to make it more robust. "cd <directory>" will issue a
+chdir syscall with the target directory as parameter. Set an eprobe on
+the sys_enter_chdir event and filter for the exact directory name. Allow
+(fault) as fallback.
+
+Link: https://lore.kernel.org/all/20260804194705.760893-1-martin@kaiser.cx/
+
+Fixes: 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING pointer")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202607151010.b68428e1-lkp@intel.com
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc  | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index c300eb0202620..e2322693d0c32 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,16 +1,16 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+ clear_dynamic_events
+ SYSTEM="syscalls"
+-EVENT="sys_enter_openat"
++EVENT="sys_enter_chdir"
+ FIELD="filename"
+-EPROBE="eprobe_open"
++EPROBE="eprobe_chdir"
+ OPTIONS="file=+0(\$filename):ustring"
+ echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+@@ -18,20 +18,14 @@ grep -q "$EPROBE" dynamic_events
+ test -d events/eprobes/$EPROBE
+ echo 1 > events/eprobes/$EPROBE/enable
+-ls
++cd /sys/kernel/tracing
+ echo 0 > events/eprobes/$EPROBE/enable
+-content=`grep '^ *ls-' trace | grep 'file='`
+-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
+-
++content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
+ if [ -z "$content" ]; then
+       exit_fail
+ fi
+-if [ ! -z "$nocontent" ]; then
+-      exit_fail
+-fi
+-
+ echo "-:$EPROBE" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+-- 
+2.53.0
+
index 92cae60f747fa7a694c62841a59a52e1c6b898e1..3aa996e848b29b9cbe52ce2cd1943786d520a9e1 100644 (file)
@@ -3,3 +3,64 @@ selftests-bpf-fail-unbound-udp-on-sockmap-update.patch
 drm-amd-display-add-av-mute-wait-frames-to-dce110_se.patch
 drm-amd-display-check-for-tg-ops-in-dce110_set_avmut.patch
 s390-zcrypt-fix-missing-mem-scrub-at-clear-key-impor.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
+drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
+net-hns3-fix-speed-configuration-residue-after-drive.patch
+revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch
+net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
+pds_core-keep-the-health-thread-stopped-during-reset.patch
+pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch
+netfilter-ipset-switch-ext_size-to-atomic64_t.patch
+ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
+ipvs-return-the-csum-validation-for-forward-hook.patch
+watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch
+btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+devlink-fix-net-namespace-reference-leak-in-reload.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch
+bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch
+bpf-tcp-get-rid-of-st_bucket_done.patch
+bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch
+bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch
+bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
+vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
+vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch
+tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
+xsk-require-at-least-16-bytes-of-tx-metadata.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
+hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
+hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
+selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
+bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch
+bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch
+bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch
+bnxt_en-fix-ptp-pps-setting-bug.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
+net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
+hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
+hwmon-ads7828-fix-external-vref-regulator-handling.patch
+hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch
+hwmon-ltc4282-clamp-negative-current-limits.patch
+hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch
diff --git a/queue-6.12/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch b/queue-6.12/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
new file mode 100644 (file)
index 0000000..237e73b
--- /dev/null
@@ -0,0 +1,61 @@
+From cddddf06cb080f0040e0f289d29fcb155a4a4744 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 20:08:06 -0700
+Subject: tcp: do not change rcv_ssthresh in tcp_measure_rcv_mss()
+
+From: Nathan Gao <zcgao@amazon.com>
+
+[ Upstream commit 0e125ecfe20c077625cf0be8d750d5c3abc0dce9 ]
+
+Commit f5da7c45188e ("tcp: adjust rcvq_space after updating scaling
+ratio") replaced the direct window_clamp update in tcp_measure_rcv_mss()
+with a call to tcp_set_window_clamp(), a helper that implements the
+TCP_WINDOW_CLAMP setsockopt. As a side effect, the helper also shrinks
+rcv_ssthresh via __tcp_adjust_rcv_ssthresh().
+
+As a result, each scaling_ratio decrease detected by
+tcp_measure_rcv_mss() also cuts rcv_ssthresh. Elsewhere in TCP,
+rcv_ssthresh is usually cut under memory pressure and grows via
+tcp_grow_window().
+
+Flows whose segment sizes vary keep scaling_ratio oscillating, which
+leads to an unstable rcv_ssthresh: a dip of rcv_ssthresh only recovers
+via tcp_grow_window(), keeping the advertised window at a relatively
+low level even after the ratio itself has recovered, and can even stall
+the sender.
+
+Observed on a customer's proxy gateway after upgrading from kernel 6.1
+to 6.12: in the worst case, rcv_ssthresh was cut in half by a
+scaling_ratio dip. P99 latency jumped from <10ms on 6.1 to ~100ms on
+6.12, and almost returned to the 6.1 level with this patch applied.
+
+Restore the plain WRITE_ONCE() update of window_clamp, as introduced
+in commit a2cbb1603943 ("tcp: Update window clamping condition"), and
+keep the rcvq_space.space adjustment. Now rcv_ssthresh is decoupled from
+scaling_ratio changes in tcp_measure_rcv_mss().
+
+Fixes: f5da7c45188e ("tcp: adjust rcvq_space after updating scaling ratio")
+Signed-off-by: Nathan Gao <zcgao@amazon.com>
+Link: https://patch.msgid.link/20260725030806.28135-1-zcgao@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index e57917aefd508..2fb68455679a8 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -247,7 +247,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
+                               struct tcp_sock *tp = tcp_sk(sk);
+                               val = tcp_win_from_space(sk, sk->sk_rcvbuf);
+-                              tcp_set_window_clamp(sk, val);
++                              WRITE_ONCE(tp->window_clamp, val);
+                               if (tp->window_clamp < tp->rcvq_space.space)
+                                       tp->rcvq_space.space = tp->window_clamp;
+-- 
+2.53.0
+
diff --git a/queue-6.12/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch b/queue-6.12/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
new file mode 100644 (file)
index 0000000..1d573f4
--- /dev/null
@@ -0,0 +1,72 @@
+From 8745835bc1b74aa07d0199ef3d21c486b6da09ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:17:38 +0800
+Subject: tcp: fix TFO max_qlen accounting across reuseport migration
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit a0ab2ba83e35159d81cec830a92e885ecf8139be ]
+
+A listener's TCP_FASTOPEN max_qlen stops being accurate and lets through
+far more pending Fast Open requests than it was configured for.
+
+This only shows up with SO_REUSEPORT listener migration, where closing a
+listener hands its still-pending TFO children over to a surviving one.
+
+fastopenq.qlen is charged in tcp_fastopen_create_child() when the child
+is created and uncharged in reqsk_fastopen_remove() when the handshake
+completes.  The uncharge follows rsk_listener of the request the child
+points at, and inet_reqsk_clone() has repointed the child at a new
+request owned by the new listener, so the ++ and the -- land on two
+different sockets.  The new listener's qlen drifts negative and its
+limit no longer binds.
+
+Charge the new listener during migration, like reqsk_queue_migrated()
+already does for queue->young and queue->qlen.
+
+Fixes: 54b92e841937 ("tcp: Migrate TCP_ESTABLISHED/TCP_SYN_RECV sockets in accept queues.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260803061739.134737-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index 5ff45bc854422..91dcdb7567ace 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -987,11 +987,23 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
+       nreq->rsk_listener = sk;
+-      /* We need not acquire fastopenq->lock
+-       * because the child socket is locked in inet_csk_listen_stop().
+-       */
+-      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
++      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener) {
++              struct fastopen_queue *fastopenq;
++
++              /* reqsk_fastopen_remove() will uncharge nreq->rsk_listener,
++               * that is @sk, so charge it here.  Unlike the listener
++               * being closed, @sk is live and needs its lock.
++               */
++              fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
++              spin_lock_bh(&fastopenq->lock);
++              fastopenq->qlen++;
++              spin_unlock_bh(&fastopenq->lock);
++
++              /* We need not acquire fastopenq->lock
++               * because the child socket is locked in inet_csk_listen_stop().
++               */
+               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
++      }
+       return nreq;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-6.12/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..e148487
--- /dev/null
@@ -0,0 +1,45 @@
+From eeed188adcc1abaa2277217059a79b95f9b207c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 2b875369d5232..137a7914c3044 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -458,7 +458,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-6.12/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-6.12/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..331dead
--- /dev/null
@@ -0,0 +1,53 @@
+From 73c2b0537a3cf7795645a0026f10b90ffad884f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 99688014901ed..04246d1f8b3e7 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -22,17 +22,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-6.12/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch b/queue-6.12/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch
new file mode 100644 (file)
index 0000000..6bdc7d2
--- /dev/null
@@ -0,0 +1,61 @@
+From f521737662e751a84c1220161011c413eecf026b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jul 2026 16:15:37 +0200
+Subject: vdpa/mlx5: Fix buffer length in create_direct_keys()
+
+From: Christian Borntraeger <borntraeger@linux.ibm.com>
+
+[ Upstream commit 727e1f569855df83579edbd73dcb4a0723543a12 ]
+
+We have seen in our CI the following KASAN message:
+BUG: KASAN: slab-out-of-bounds in cmd_exec+0x550/0xca0 [mlx5_core]
+Read of size 272 at addr 0000000176795020 by task qemu-system-s39/82764
+[...]
+[<000011388ab3a7a0>] cmd_exec+0x550/0xca0 [mlx5_core]
+[<000011388ab3b61c>] mlx5_cmd_exec_cb+0x25c/0x4f0 [mlx5_core]
+[<000011388b21e82e>] mlx5_vdpa_exec_async_cmds+0x22e/0x5e0 [mlx5_vdpa]
+[<000011388b21fd44>] create_direct_keys+0x954/0xef0 [mlx5_vdpa]
+[...]
+The buggy address is located 4128 bytes inside of
+allocated 4384-byte region [0000000176794000, 0000000176795120)
+
+So in essence we read 16 bytes beyond 4384-byte allocation.
+create_direct_keys calculates the pointer and length for in and out
+buffers.
+The size calculation for in includes the entire structure
+size (out + in + mtt[]) but the pointer passed to cmd_exec points only
+to the 'in' field, skipping the 'out' field.
+
+This causes mlx5_copy_to_msg() to read beyond the allocated buffer
+by sizeof(out) bytes when copying command data.
+
+Properly calculate the input size to match the pointer and allocation size.
+
+Fixes: 0071b138d44a ("vdpa/mlx5: Create direct MKEYs in parallel")
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Tested-by: Dragos Tatulea <dtatulea@nvidia.com>
+Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <20260706141537.3510294-1-borntraeger@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/core/mr.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
+index c7a20278bc3ca..27abbe69b55cd 100644
+--- a/drivers/vdpa/mlx5/core/mr.c
++++ b/drivers/vdpa/mlx5/core/mr.c
+@@ -234,7 +234,8 @@ static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *
+               cmds[i].out = cmd_mem->out;
+               cmds[i].outlen = sizeof(cmd_mem->out);
+               cmds[i].in = cmd_mem->in;
+-              cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount);
++              cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount) -
++                              offsetof(struct mlx5_create_mkey_mem, in);
+               fill_create_direct_mr(mvdev, dmr, cmd_mem);
+-- 
+2.53.0
+
diff --git a/queue-6.12/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch b/queue-6.12/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
new file mode 100644 (file)
index 0000000..3f94821
--- /dev/null
@@ -0,0 +1,56 @@
+From cfc7f69b3756b93dcef4b1ceef8f776b4f9282eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:02:02 -0700
+Subject: vhost/vdpa: reject overflowing PA map page counts on 32-bit
+
+From: Yousef Alhouseen <alhouseenyousef@gmail.com>
+
+[ Upstream commit 0619aaa34c0c2a2dcb07f0e9c8a34e7efb8c4cdf ]
+
+vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
+size before computing the number of pages to pin. On 32-bit systems,
+where unsigned long is narrower than u64, that addition can overflow and
+the code can pin and map fewer pages than the requested IOTLB range.
+
+Reject sizes that overflow the unsigned long page-count calculation.
+
+Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and vhost_vdpa_pa_unmap()")
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index 2464c9de67712..a47fdcb61bf36 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -1102,6 +1102,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       unsigned int gup_flags = FOLL_LONGTERM;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
++      unsigned long page_offset;
+       u64 start = iova;
+       long pinned;
+       int ret = 0;
+@@ -1114,7 +1115,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       if (perm & VHOST_ACCESS_WO)
+               gup_flags |= FOLL_WRITE;
+-      npages = PFN_UP(size + (iova & ~PAGE_MASK));
++      page_offset = iova & ~PAGE_MASK;
++      if (size > ULONG_MAX - page_offset) {
++              ret = -EINVAL;
++              goto free;
++      }
++
++      npages = PFN_UP(size + page_offset);
+       if (!npages) {
+               ret = -EINVAL;
+               goto free;
+-- 
+2.53.0
+
diff --git a/queue-6.12/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch b/queue-6.12/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch
new file mode 100644 (file)
index 0000000..0f39a75
--- /dev/null
@@ -0,0 +1,68 @@
+From 2dd8b4d1f264b9bcd20d171b5b46a015c112b2f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:36:28 +0300
+Subject: watchdog: bd96801_wdt: Fix timeout for enabled WDG
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit 1246aa2b6ccc8944676bd24ff3e37cc56b93b51b ]
+
+When watchdog is enabled at the probe time, the bd96801 driver retrieves
+the timeout configuration from the registers to set-up the heart-beat
+values.
+
+As Sashiko pointed out at
+https://lore.kernel.org/all/20260722085819.495211F000E9@smtp.kernel.org/
+the timeout values are incorrectly computed in driver, resulting wrong
+heartbeat. This leads to devere problems if watchdog was enabled at probe
+time.
+
+According to the data-sheet, the "too fast" ping limit is configured as
+multiple of FASTNG_MIN. Furthermore, the "too slow" ping limit is
+configured as multiples of "too fast" timeout. The FASTNG_MIN is set to
+11, meaning 1.1 mS and "too fast" and "too slow" limits are computed from
+this. Hence, converting the limits to mS should be done by dividing by 10,
+not by dividing by USEC_PER_MSEC.
+
+Fix this by dividing the timeout values with correct scaling factor.
+
+While at it, fix whitespace problem (double empty line).
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Fixes: 09dad69757b6 ("watchdog: ROHM BD96801 PMIC WDG driver")
+Link: https://lore.kernel.org/r/amxskHmQbi9v-8_l@mva-rohm
+[groeck: Added reference to whitespace change to description]
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/bd96801_wdt.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/watchdog/bd96801_wdt.c b/drivers/watchdog/bd96801_wdt.c
+index 12b74fd2bc052..a25b7cf1488b2 100644
+--- a/drivers/watchdog/bd96801_wdt.c
++++ b/drivers/watchdog/bd96801_wdt.c
+@@ -169,7 +169,6 @@ static int bd96801_set_wdt_mode(struct wdtbd96801 *w, unsigned int hw_margin,
+       int fastng, slowng, type, ret, reg, mask;
+       struct device *dev = w->dev;
+-
+       if (hw_margin_min * 1000 > FASTNG_MAX_US) {
+               dev_err(dev, "Unsupported fast timeout %u uS [max %u]\n",
+                       hw_margin_min * 1000, FASTNG_MAX_US);
+@@ -258,10 +257,10 @@ static int bd96801_set_heartbeat_from_hw(struct wdtbd96801 *w,
+       fast = FASTNG_MIN << sel;
+       sel = (val & BD96801_WD_RATIO_MASK) + 1;
+-      w->wdt.max_hw_heartbeat_ms = (fast << sel) / USEC_PER_MSEC;
++      w->wdt.max_hw_heartbeat_ms = (fast << sel) / 10;
+       if ((conf_reg & BD96801_WD_TYPE_MASK) == BD96801_WD_TYPE_WIN)
+-              w->wdt.min_hw_heartbeat_ms = fast / USEC_PER_MSEC;
++              w->wdt.min_hw_heartbeat_ms = fast / 10;
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/xsk-require-at-least-16-bytes-of-tx-metadata.patch b/queue-6.12/xsk-require-at-least-16-bytes-of-tx-metadata.patch
new file mode 100644 (file)
index 0000000..e941494
--- /dev/null
@@ -0,0 +1,45 @@
+From a387a9a36e20bee53f038ba56377a4b76fa180bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:54 -0700
+Subject: xsk: require at least 16 bytes of TX metadata
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 1bb30b181d9f0484e141f8411e15ed906d5c6780 ]
+
+AF_XDP accepts a TX metadata length as small as eight bytes, but every
+supported request needs the flags plus at least one eight-byte request
+field. Such short metadata also lets the kernel read beyond the registered
+area.
+
+Require 16 bytes rather than sizeof(struct xsk_tx_metadata) to preserve
+compatibility with applications that do not use launch-time metadata.
+
+Fixes: 341ac980eab9 ("xsk: Support tx_metadata_len")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reported-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Link: https://lore.kernel.org/netdev/20260720155210.34229-1-blbllhy@gmail.com/
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-2-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xdp_umem.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
+index 9ec7bd948acc7..81ffda5501078 100644
+--- a/net/xdp/xdp_umem.c
++++ b/net/xdp/xdp_umem.c
+@@ -209,6 +209,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
+       if (mr->flags & XDP_UMEM_TX_METADATA_LEN) {
+               if (mr->tx_metadata_len >= 256 || mr->tx_metadata_len % 8)
+                       return -EINVAL;
++              if (mr->tx_metadata_len < 16)
++                      return -EINVAL;
+               umem->tx_metadata_len = mr->tx_metadata_len;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch b/queue-6.18/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
new file mode 100644 (file)
index 0000000..3b93119
--- /dev/null
@@ -0,0 +1,39 @@
+From e103ae3ce08a81e9f370eed76a64937c46035332 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 14:57:22 -0700
+Subject: ARM: dts: BCM5301X: fix PCIe controller 2 second interrupt
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit bab4d538f8485e0d48538fcb82b285df3779278e ]
+
+PCIe controller 2 has interrupts 0-4 mapping to GIC SPI 138-142. The
+mapping for interrupt 1 was incorrectly set to 138 due to a copy-paste
+error. Fix it to 139.
+
+Assisted-by: opencode:big-pickle
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://lore.kernel.org/r/20260725215722.9323-1-rosenp@gmail.com
+Fixes: 3b3e35b279be ("ARM: dts: BCM5301X: Relicense AXI interrupts code to the GPL 2.0+ / MIT")
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/broadcom/bcm-ns.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+index d0d5f7e52a917..f08d0a27de0b4 100644
+--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
++++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+@@ -138,7 +138,7 @@ axi@18000000 {
+                       /* PCIe Controller 2 */
+                       <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+-                      <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
++                      <0x00014000 1 &gic GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-6.18/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..b90eb8b
--- /dev/null
@@ -0,0 +1,50 @@
+From 4500feb8c4badefb3b7d7405c51046d084fd1f87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 41891d3aa1247..4c1fc9983746c 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -32,6 +32,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -60,6 +61,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch b/queue-6.18/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch
new file mode 100644 (file)
index 0000000..9b15d1d
--- /dev/null
@@ -0,0 +1,52 @@
+From 17e2b92983b06e1a1448635e9a75164a4ef5cb5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 21:45:27 +0100
+Subject: arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual
+ timer
+
+From: Daniel Drake <dan@reactivated.net>
+
+[ Upstream commit 75952cfc7752c52a2b692b59d34ce160d3edabb2 ]
+
+Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to EL2
+virtual timer when running VHE") causes boot to hang on Raspberry Pi 5.
+The newly-selected EL2 virtual timer does not generate any interrupts,
+even though the GIC_DIST_ENABLE_SET flag has been confirmed set via
+readback.
+
+It is highly unusual that this timer interrupt is non-operational because
+this is a standard GIC interrupt corresponding to a standard Cortex-A76
+CPU timer. However, Broadcom have confirmed for this SoC:
+
+> the interrupt line was never connected in the first place as this was
+> not identified as being a requirement
+
+Remove the corresponding DeviceTree entry.
+
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
+Fixes: faa3381267d0 ("arm64: dts: broadcom: Add minimal support for Raspberry Pi 5")
+Signed-off-by: Daniel Drake <dan@reactivated.net>
+Link: https://lore.kernel.org/r/20260716-bcm2712-el2-v2-1-e708f7fb42fa@reactivated.net
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+index d771694787b28..45a382f75b5ec 100644
+--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
++++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+@@ -651,8 +651,6 @@ IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
+                                         IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
+-                                        IRQ_TYPE_LEVEL_LOW)>,
+-                           <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
+                                         IRQ_TYPE_LEVEL_LOW)>;
+       };
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch b/queue-6.18/arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch
new file mode 100644 (file)
index 0000000..03831e4
--- /dev/null
@@ -0,0 +1,99 @@
+From 76f8ef835980d62931cab55379a8488d334ae727 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Apr 2026 02:38:51 +0530
+Subject: arm64: dts: qcom: purwa: Fix GPU IOMMU property
+
+From: Akhil P Oommen <akhilpo@oss.qualcomm.com>
+
+[ Upstream commit 4cd774c1feb3f720265c512174c5c3312eca1be2 ]
+
+Purwa's GPU does not support SID 1, which is typically used for
+LPAC-related traffic. Remove SID 1 from the GPU node's iommus property to
+accurately describe the hardware. This fixes the splat below, seen with
+some versions of Gunyah hypervisor:
+
+  Internal error: synchronous external abort: 0000000096000010 [#1]  SMP
+  CPU: 0 UID: 0 PID: 80 Comm: kworker/u33:2 Tainted: G   M
+  Tainted: [M]=MACHINE_CHECK
+  Hardware name: Qualcomm Technologies, Inc. Purwa IoT EVK (DT)
+  Workqueue: events_unbound deferred_probe_work_func
+  pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
+  pc : arm_smmu_write_s2cr+0x9c/0xbc
+  lr : arm_smmu_master_install_s2crs+0x78/0xa4
+  sp : ffff80008039b570
+  x29: ffff80008039b570 x28: 0000000000000000 x27: ffffaddd62f1ab78
+  x26: ffff00080a4ff280 x25: 0000000000000018 x24: ffff00080b896480
+  x23: ffff00080ba9b7a0 x22: ffff00080bb05160 x21: 0000000000000000
+  x20: 0000000000000000 x19: 0000000000000001 x18: 00000000ffffffff
+  x17: 0000000000000000 x16: 0000000000000000 x15: ffff80008039b1d0
+  x14: ffff80010039b37d x13: 00746c7561662d74 x12: 0000000000000000
+  x11: ffff00080b7fbd98 x10: ffffffffffffffc0 x9 : ffffffffffffffff
+  x8 : 0000000000000228 x7 : 0000000000000e87 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : ffff00080a4ff280 x3 : 0000000000000000
+  x2 : ffff800082a40c04 x1 : 0000000000000000 x0 : ffff800082a40000
+  Call trace:
+   arm_smmu_write_s2cr+0x9c/0xbc (P)
+   arm_smmu_master_install_s2crs+0x78/0xa4
+   arm_smmu_attach_dev+0xb0/0x1d8
+   __iommu_device_set_domain+0x84/0x11c
+   __iommu_group_set_domain_internal+0x60/0x120
+   __iommu_attach_group+0x88/0x9c
+   iommu_attach_device+0x6c/0xa0
+   msm_iommu_new.part.0+0x84/0xe4 [msm]
+   msm_iommu_gpu_new+0x3c/0x104 [msm]
+   adreno_iommu_create_vm+0x24/0xc8 [msm]
+   a6xx_create_vm+0x48/0x78 [msm]
+   msm_gpu_init+0x2d8/0x508 [msm]
+   adreno_gpu_init+0x208/0x324 [msm]
+   a6xx_gpu_init+0x604/0x8cc [msm]
+   adreno_bind+0xb4/0x124 [msm]
+   component_bind_all+0x114/0x23c
+   msm_drm_init+0x1b0/0x1ec [msm]
+   msm_drm_bind+0x30/0x3c [msm]
+   try_to_bring_up_aggregate_device+0x164/0x1d0
+   __component_add+0xa4/0x16c
+   component_add+0x14/0x20
+   msm_dp_display_probe_tail+0x4c/0xac [msm]
+   msm_dp_auxbus_done_probe+0x14/0x20 [msm]
+   dp_aux_ep_probe+0x4c/0xf4 [drm_dp_aux_bus]
+   really_probe+0xbc/0x29c
+   __driver_probe_device+0x78/0x12c
+   driver_probe_device+0x3c/0x15c
+   __device_attach_driver+0xb8/0x134
+   bus_for_each_drv+0x88/0xe8
+   __device_attach+0xa0/0x190
+   device_initial_probe+0x50/0x54
+   bus_probe_device+0x38/0xa4
+   deferred_probe_work_func+0x88/0xc0
+   process_one_work+0x148/0x28c
+   worker_thread+0x2cc/0x3d4
+   kthread+0x12c/0x204
+   ret_from_fork+0x10/0x20
+  ---[ end trace 0000000000000000 ]---
+
+Fixes: 1aa0b4e36436 ("arm64: dts: qcom: x1p42100: Add GPU support")
+Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260410-purwa-gpu-dt-fix-v1-1-4637892156cf@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/purwa.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi
+index 2cecd2dd0de8c..a02b39f98f0b2 100644
+--- a/arch/arm64/boot/dts/qcom/purwa.dtsi
++++ b/arch/arm64/boot/dts/qcom/purwa.dtsi
+@@ -33,6 +33,8 @@ &gmu {
+ &gpu {
+       compatible = "qcom,adreno-43030c00", "qcom,adreno";
++      iommus = <&adreno_smmu 0 0x0>;
++
+       nvmem-cells = <&gpu_speed_bin>;
+       nvmem-cell-names = "speed_bin";
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-qcom-rename-x1e80100-to-hamoa.patch b/queue-6.18/arm64-dts-qcom-rename-x1e80100-to-hamoa.patch
new file mode 100644 (file)
index 0000000..ceee591
--- /dev/null
@@ -0,0 +1,323 @@
+From 807dad9bdf0b161d92887feb27f705ed28503ec2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Sep 2025 14:01:55 +0300
+Subject: arm64: dts: qcom: rename x1e80100 to hamoa
+
+From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+
+[ Upstream commit 8c0b058ab5983a4be6690a76be9b0294853e8e55 ]
+
+The X1E80100 and several other similar names (X1E78100, X1E001DE) all
+belong to the platform now known as 'hamoa'. Follow the example of
+'lemans' and rename the x1e80100.dtsi to hamoa.dtsi and
+x1e80100-pmics.dtsi to hamoa-pmics.dtsi.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20250923-rename-dts-v1-2-21888b68c781@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 4cd774c1feb3 ("arm64: dts: qcom: purwa: Fix GPU IOMMU property")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi                   | 4 ++--
+ .../boot/dts/qcom/{x1e80100-pmics.dtsi => hamoa-pmics.dtsi}   | 0
+ arch/arm64/boot/dts/qcom/{x1e80100.dtsi => hamoa.dtsi}        | 0
+ arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi             | 2 +-
+ arch/arm64/boot/dts/qcom/x1-crd.dtsi                          | 2 +-
+ arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi                   | 2 +-
+ arch/arm64/boot/dts/qcom/x1e001de-devkit.dts                  | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi   | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts       | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts        | 2 +-
+ arch/arm64/boot/dts/qcom/x1e80100-crd.dts                     | 2 +-
+ .../boot/dts/qcom/x1e80100-dell-inspiron-14-plus-7441.dts     | 2 +-
+ arch/arm64/boot/dts/qcom/x1e80100-dell-latitude-7455.dts      | 2 +-
+ arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts         | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e80100-hp-omnibook-x14.dts         | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts      | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi      | 4 ++--
+ arch/arm64/boot/dts/qcom/x1e80100-qcp.dts                     | 4 ++--
+ arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts         | 2 +-
+ arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts     | 2 +-
+ arch/arm64/boot/dts/qcom/x1p42100.dtsi                        | 4 ++--
+ 21 files changed, 29 insertions(+), 29 deletions(-)
+ rename arch/arm64/boot/dts/qcom/{x1e80100-pmics.dtsi => hamoa-pmics.dtsi} (100%)
+ rename arch/arm64/boot/dts/qcom/{x1e80100.dtsi => hamoa.dtsi} (100%)
+
+diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi
+index 1aead50b8920b..4de7c0abb25a1 100644
+--- a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi
++++ b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi
+@@ -3,8 +3,8 @@
+  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+  */
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi
+similarity index 100%
+rename from arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi
+rename to arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
+similarity index 100%
+rename from arch/arm64/boot/dts/qcom/x1e80100.dtsi
+rename to arch/arm64/boot/dts/qcom/hamoa.dtsi
+diff --git a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
+index ee3c8c5e2c50c..69eccad1a09c2 100644
+--- a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
+@@ -11,7 +11,7 @@
+ #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "ASUS Zenbook A14";
+diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi
+index 3c9455fede5c0..5e324f35547a4 100644
+--- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi
+@@ -9,7 +9,7 @@
+ #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "Qualcomm Technologies, Inc. X1E80100 CRD";
+diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+index 5b5a10a31a253..aee3fafbe7fcc 100644
+--- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+@@ -12,7 +12,7 @@
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       chassis-type = "laptop";
+diff --git a/arch/arm64/boot/dts/qcom/x1e001de-devkit.dts b/arch/arm64/boot/dts/qcom/x1e001de-devkit.dts
+index bfc649d4b643c..701f35af7d5cd 100644
+--- a/arch/arm64/boot/dts/qcom/x1e001de-devkit.dts
++++ b/arch/arm64/boot/dts/qcom/x1e001de-devkit.dts
+@@ -8,8 +8,8 @@
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "Qualcomm Technologies, Inc. X1E001DE Snapdragon Devkit for Windows";
+diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
+index 654cbce9d6ecb..169726984d3b0 100644
+--- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
+@@ -12,8 +12,8 @@
+ #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "Lenovo ThinkPad T14s Gen 6";
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
+index 0113d856b3ad4..f2960953e608f 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
+@@ -11,8 +11,8 @@
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+ #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "ASUS Vivobook S 15";
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts
+index 0d0bcc50207d7..c3cd04c9703d3 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts
+@@ -6,7 +6,7 @@
+ /dts-v1/;
+-#include "x1e80100.dtsi"
++#include "hamoa.dtsi"
+ #include "x1-asus-zenbook-a14.dtsi"
+ / {
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
+index dfc378e1a056a..429deffcf3e9d 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
+@@ -5,7 +5,7 @@
+ /dts-v1/;
+-#include "x1e80100.dtsi"
++#include "hamoa.dtsi"
+ #include "x1-crd.dtsi"
+ / {
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-dell-inspiron-14-plus-7441.dts b/arch/arm64/boot/dts/qcom/x1e80100-dell-inspiron-14-plus-7441.dts
+index cf2a7c2628881..75e10d97c3867 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-dell-inspiron-14-plus-7441.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-dell-inspiron-14-plus-7441.dts
+@@ -4,7 +4,7 @@
+  */
+ /dts-v1/;
+-#include "x1e80100.dtsi"
++#include "hamoa.dtsi"
+ #include "x1-dell-thena.dtsi"
+ / {
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-dell-latitude-7455.dts b/arch/arm64/boot/dts/qcom/x1e80100-dell-latitude-7455.dts
+index 32ad9679550ef..a8ff7ef258a13 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-dell-latitude-7455.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-dell-latitude-7455.dts
+@@ -4,7 +4,7 @@
+  */
+ /dts-v1/;
+-#include "x1e80100.dtsi"
++#include "hamoa.dtsi"
+ #include "x1-dell-thena.dtsi"
+ / {
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts b/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts
+index 58f8caaa72580..c1f49cba61fc4 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts
+@@ -12,8 +12,8 @@
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "Dell XPS 13 9345";
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-hp-omnibook-x14.dts b/arch/arm64/boot/dts/qcom/x1e80100-hp-omnibook-x14.dts
+index e5a839d458402..b79e59e1c413a 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-hp-omnibook-x14.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-hp-omnibook-x14.dts
+@@ -6,8 +6,8 @@
+ /dts-v1/;
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ #include "x1-hp-omnibook-x14.dtsi"
+ / {
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
+index e0642fe8343f6..56e4d13cca111 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
+@@ -9,8 +9,8 @@
+ #include <dt-bindings/input/gpio-keys.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "Lenovo Yoga Slim 7x";
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi
+index ed468b93ba50e..3b319f65dde1e 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi
+@@ -9,8 +9,8 @@
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       aliases {
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+index 4a9b6d791e7f4..5a121fc449401 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+@@ -8,8 +8,8 @@
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1e80100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa.dtsi"
++#include "hamoa-pmics.dtsi"
+ / {
+       model = "Qualcomm Technologies, Inc. X1E80100 QCP";
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts b/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts
+index 6696cab2de3ec..47ab0c5b30341 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts
+@@ -3,7 +3,7 @@
+ /dts-v1/;
+ #include "x1p42100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa-pmics.dtsi"
+ #include "x1-hp-omnibook-x14.dtsi"
+ /delete-node/ &pmc8380_6;
+ /delete-node/ &pmc8380_6_thermal;
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts b/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts
+index 1ac46cdc43861..f7d372d2e9612 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts
+@@ -14,7 +14,7 @@
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+ #include "x1p42100.dtsi"
+-#include "x1e80100-pmics.dtsi"
++#include "hamoa-pmics.dtsi"
+ /delete-node/ &pmc8380_6;
+ /delete-node/ &pmc8380_6_thermal;
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100.dtsi b/arch/arm64/boot/dts/qcom/x1p42100.dtsi
+index 10d26958d3c66..2cecd2dd0de8c 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1p42100.dtsi
+@@ -3,8 +3,8 @@
+  * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+-/* X1P42100 is heavily based on X1E80100, with some meaningful differences */
+-#include "x1e80100.dtsi"
++/* X1P42100 is heavily based on hamoa, with some meaningful differences */
++#include "hamoa.dtsi"
+ /delete-node/ &bwmon_cluster0;
+ /delete-node/ &cluster_pd2;
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-qcom-rename-x1p42100-to-purwa.patch b/queue-6.18/arm64-dts-qcom-rename-x1p42100-to-purwa.patch
new file mode 100644 (file)
index 0000000..ffcf0fa
--- /dev/null
@@ -0,0 +1,84 @@
+From 161ad2851d1c0a69ea962ce11d1d4e4eec2544fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Oct 2025 20:20:15 +0200
+Subject: arm64: dts: qcom: rename x1p42100 to purwa
+
+From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+
+[ Upstream commit ef659a5bd91bed7fae2c2a150f8ecca06599ac03 ]
+
+Follow the example of other platforms and rename X1P42100 to purwa.dtsi.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20251030-rename-dts-2-v1-3-80c0b81c4d77@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 4cd774c1feb3 ("arm64: dts: qcom: purwa: Fix GPU IOMMU property")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/{x1p42100.dtsi => purwa.dtsi}    | 0
+ arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi   | 2 +-
+ arch/arm64/boot/dts/qcom/x1p42100-crd.dts                 | 2 +-
+ arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts     | 2 +-
+ arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts | 2 +-
+ 5 files changed, 4 insertions(+), 4 deletions(-)
+ rename arch/arm64/boot/dts/qcom/{x1p42100.dtsi => purwa.dtsi} (100%)
+
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi
+similarity index 100%
+rename from arch/arm64/boot/dts/qcom/x1p42100.dtsi
+rename to arch/arm64/boot/dts/qcom/purwa.dtsi
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi
+index 7ccb2076bab66..22470a97e1e39 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi
+@@ -6,7 +6,7 @@
+ /dts-v1/;
+-#include "x1p42100.dtsi"
++#include "purwa.dtsi"
+ #include "x1-asus-zenbook-a14.dtsi"
+ /delete-node/ &pmc8380_6;
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-crd.dts b/arch/arm64/boot/dts/qcom/x1p42100-crd.dts
+index cf999c2cf8d4e..7ed4116b95904 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-crd.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-crd.dts
+@@ -5,7 +5,7 @@
+ /dts-v1/;
+-#include "x1p42100.dtsi"
++#include "purwa.dtsi"
+ #include "x1-crd.dtsi"
+ /delete-node/ &pmc8380_6;
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts b/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts
+index 47ab0c5b30341..0f338e457abda 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-hp-omnibook-x14.dts
+@@ -2,7 +2,7 @@
+ /dts-v1/;
+-#include "x1p42100.dtsi"
++#include "purwa.dtsi"
+ #include "hamoa-pmics.dtsi"
+ #include "x1-hp-omnibook-x14.dtsi"
+ /delete-node/ &pmc8380_6;
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts b/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts
+index f7d372d2e9612..3186e79e862de 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-lenovo-thinkbook-16.dts
+@@ -13,7 +13,7 @@
+ #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+-#include "x1p42100.dtsi"
++#include "purwa.dtsi"
+ #include "hamoa-pmics.dtsi"
+ /delete-node/ &pmc8380_6;
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-qcom-rework-x1-based-asus-zenbook-a14-s-di.patch b/queue-6.18/arm64-dts-qcom-rework-x1-based-asus-zenbook-a14-s-di.patch
new file mode 100644 (file)
index 0000000..266ab7e
--- /dev/null
@@ -0,0 +1,471 @@
+From 15d4f31b0ddff9eb4816a2093625418b4558247b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Sep 2025 15:21:36 +0200
+Subject: arm64: dts: qcom: Rework X1-based Asus Zenbook A14's displays
+
+From: Aleksandrs Vinarskis <alex@vinarskis.com>
+
+[ Upstream commit 462b39931cab3415ffc47863a58372399e600f4f ]
+
+The laptop comes in two variants:
+
+* UX3407RA, higher end, FHD+ OLED or WOXGA+ OLED panels
+* UX3407QA, lower end, FHD+ OLED or FHD+ LCD panels
+
+Even though all three panels work with "edp-panel", unfortunately the
+brightness adjustmenet of LCD panel is PWM based, requiring a dedicated
+device-tree. Convert "x1p42100-asus-zenbook-a14.dts" into ".dtsi" to
+allow for this split, introduce new LCD variant. Leave current variant
+without postfix and with the unchanged model name, as some distros
+(eg. Ubuntu) rely on this for automatic device-tree detection during
+kernel installation/upgrade.
+
+As dedicated device-tree is required, update compatibles of OLED
+variants to correct ones. Keep "edp-panel" as fallback, since it is
+enough to make the panels work.
+
+While at it moving .dts, .dtsi around, drop 'model' from the top level
+x1-asus-zenbook-a14.dtsi as well.
+
+Co-developed-by: Jens Glathe <jens.glathe@oldschoolsolutions.biz>
+Signed-off-by: Jens Glathe <jens.glathe@oldschoolsolutions.biz>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Signed-off-by: Aleksandrs Vinarskis <alex@vinarskis.com>
+Link: https://lore.kernel.org/r/20250927-zenbook-improvements-v3-2-d46c7368dc70@vinarskis.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 4cd774c1feb3 ("arm64: dts: qcom: purwa: Fix GPU IOMMU property")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/Makefile             |   2 +
+ .../boot/dts/qcom/x1-asus-zenbook-a14.dtsi    |   7 +-
+ .../dts/qcom/x1e80100-asus-zenbook-a14.dts    |   8 +
+ .../qcom/x1p42100-asus-zenbook-a14-lcd.dts    |  62 ++++++++
+ .../dts/qcom/x1p42100-asus-zenbook-a14.dts    | 133 +----------------
+ .../dts/qcom/x1p42100-asus-zenbook-a14.dtsi   | 138 ++++++++++++++++++
+ 6 files changed, 218 insertions(+), 132 deletions(-)
+ create mode 100644 arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14-lcd.dts
+ create mode 100644 arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi
+
+diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
+index 296688f7cb265..dffdb219f33dc 100644
+--- a/arch/arm64/boot/dts/qcom/Makefile
++++ b/arch/arm64/boot/dts/qcom/Makefile
+@@ -344,6 +344,8 @@ x1e80100-qcp-el2-dtbs      := x1e80100-qcp.dtb x1-el2.dtbo
+ dtb-$(CONFIG_ARCH_QCOM)       += x1e80100-qcp.dtb x1e80100-qcp-el2.dtb
+ x1p42100-asus-zenbook-a14-el2-dtbs    := x1p42100-asus-zenbook-a14.dtb x1-el2.dtbo
+ dtb-$(CONFIG_ARCH_QCOM)       += x1p42100-asus-zenbook-a14.dtb x1p42100-asus-zenbook-a14-el2.dtb
++x1p42100-asus-zenbook-a14-lcd-el2-dtbs        := x1p42100-asus-zenbook-a14-lcd.dtb x1-el2.dtbo
++dtb-$(CONFIG_ARCH_QCOM)       += x1p42100-asus-zenbook-a14-lcd.dtb x1p42100-asus-zenbook-a14-lcd-el2.dtb
+ x1p42100-crd-el2-dtbs := x1p42100-crd.dtb x1-el2.dtbo
+ dtb-$(CONFIG_ARCH_QCOM)       += x1p42100-crd.dtb x1p42100-crd-el2.dtb
+ x1p42100-hp-omnibook-x14-el2-dtbs := x1p42100-hp-omnibook-x14.dtb x1-el2.dtbo
+diff --git a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
+index 69eccad1a09c2..8e5c5575a5320 100644
+--- a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
+@@ -14,7 +14,6 @@
+ #include "hamoa-pmics.dtsi"
+ / {
+-      model = "ASUS Zenbook A14";
+       chassis-type = "laptop";
+       aliases {
+@@ -1005,14 +1004,10 @@ &mdss_dp3 {
+       status = "okay";
+       aux-bus {
+-              panel {
++              panel: panel {
+                       compatible = "edp-panel";
+-                      enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>;
+                       power-supply = <&vreg_edp_3p3>;
+-                      pinctrl-0 = <&edp_bl_en>;
+-                      pinctrl-names = "default";
+-
+                       port {
+                               edp_panel_in: endpoint {
+                                       remote-endpoint = <&mdss_dp3_out>;
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts
+index c3cd04c9703d3..49b12a0a7cb1e 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-zenbook-a14.dts
+@@ -22,6 +22,14 @@ &gpu_zap_shader {
+       firmware-name = "qcom/x1e80100/ASUSTeK/zenbook-a14/qcdxkmsuc8380.mbn";
+ };
++&panel {
++      compatible = "samsung,atna40cu11", "samsung,atna33xc20";
++      enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>;
++
++      pinctrl-0 = <&edp_bl_en>;
++      pinctrl-names = "default";
++};
++
+ &remoteproc_adsp {
+       firmware-name = "qcom/x1e80100/ASUSTeK/zenbook-a14/qcadsp8380.mbn",
+                       "qcom/x1e80100/ASUSTeK/zenbook-a14/adsp_dtbs.elf";
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14-lcd.dts b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14-lcd.dts
+new file mode 100644
+index 0000000000000..be756069131d7
+--- /dev/null
++++ b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14-lcd.dts
+@@ -0,0 +1,62 @@
++// SPDX-License-Identifier: BSD-3-Clause
++/*
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Aleksandrs Vinarskis <alex@vinarskis.com>
++ */
++
++/dts-v1/;
++
++#include "x1p42100-asus-zenbook-a14.dtsi"
++
++/ {
++      model = "ASUS Zenbook A14 (UX3407QA, LCD)";
++      compatible = "asus,zenbook-a14-ux3407qa-lcd", "asus,zenbook-a14-ux3407qa", "qcom,x1p42100";
++
++      backlight: backlight {
++              compatible = "pwm-backlight";
++              pwms = <&pmk8550_pwm 0 416667>;
++              enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>;
++              power-supply = <&vreg_edp_bl>;
++
++              pinctrl-0 = <&edp_bl_en>, <&edp_bl_pwm>;
++              pinctrl-names = "default";
++      };
++
++      vreg_edp_bl: regulator-edp-bl {
++              compatible = "regulator-fixed";
++
++              regulator-name = "VBL9";
++              regulator-min-microvolt = <3600000>;
++              regulator-max-microvolt = <3600000>;
++
++              gpio = <&pmc8380_3_gpios 10 GPIO_ACTIVE_HIGH>;
++              enable-active-high;
++
++              pinctrl-0 = <&edp_bl_reg_en>;
++              pinctrl-names = "default";
++
++              regulator-boot-on;
++      };
++};
++
++&panel {
++      backlight = <&backlight>;
++};
++
++&pmc8380_3_gpios {
++      edp_bl_reg_en: edp-bl-reg-en-state {
++              pins = "gpio10";
++              function = "normal";
++      };
++};
++
++&pmk8550_gpios {
++      edp_bl_pwm: edp-bl-pwm-state {
++              pins = "gpio5";
++              function = "func3";
++      };
++};
++
++&pmk8550_pwm {
++      status = "okay";
++};
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dts b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dts
+index bd75ff898601a..68cd318d69073 100644
+--- a/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dts
+@@ -6,136 +6,17 @@
+ /dts-v1/;
+-#include "x1p42100.dtsi"
+-#include "x1-asus-zenbook-a14.dtsi"
+-
+-/delete-node/ &pmc8380_6;
+-/delete-node/ &pmc8380_6_thermal;
++#include "x1p42100-asus-zenbook-a14.dtsi"
+ / {
+       model = "ASUS Zenbook A14 (UX3407QA)";
+-      compatible = "asus,zenbook-a14-ux3407qa", "qcom,x1p42100";
+-
+-      wcn6855-pmu {
+-              compatible = "qcom,wcn6855-pmu";
+-
+-              vddaon-supply = <&vreg_wcn_0p95>;
+-              vddio-supply = <&vreg_wcn_1p9>;
+-              vddpcie1p3-supply = <&vreg_wcn_1p9>;
+-              vddpcie1p9-supply = <&vreg_wcn_1p9>;
+-              vddpmu-supply = <&vreg_wcn_0p95>;
+-              vddpmucx-supply = <&vreg_wcn_0p95>;
+-              vddpmumx-supply = <&vreg_wcn_0p95>;
+-              vddrfa0p95-supply = <&vreg_wcn_0p95>;
+-              vddrfa1p3-supply = <&vreg_wcn_1p9>;
+-              vddrfa1p9-supply = <&vreg_wcn_1p9>;
+-
+-              bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>;
+-              wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>;
+-
+-              pinctrl-0 = <&wcn_bt_en>, <&wcn_wlan_en>;
+-              pinctrl-names = "default";
+-
+-              regulators {
+-                      vreg_pmu_rfa_cmn_0p8: ldo0 {
+-                              regulator-name = "vreg_pmu_rfa_cmn_0p8";
+-                      };
+-
+-                      vreg_pmu_aon_0p8: ldo1 {
+-                              regulator-name = "vreg_pmu_aon_0p8";
+-                      };
+-
+-                      vreg_pmu_wlcx_0p8: ldo2 {
+-                              regulator-name = "vreg_pmu_wlcx_0p8";
+-                      };
+-
+-                      vreg_pmu_wlmx_0p8: ldo3 {
+-                              regulator-name = "vreg_pmu_wlmx_0p8";
+-                      };
+-
+-                      vreg_pmu_btcmx_0p8: ldo4 {
+-                              regulator-name = "vreg_pmu_btcmx_0p8";
+-                      };
+-
+-                      vreg_pmu_pcie_1p8: ldo5 {
+-                              regulator-name = "vreg_pmu_pcie_1p8";
+-                      };
+-
+-                      vreg_pmu_pcie_0p9: ldo6 {
+-                              regulator-name = "vreg_pmu_pcie_0p9";
+-                      };
+-
+-                      vreg_pmu_rfa_0p8: ldo7 {
+-                              regulator-name = "vreg_pmu_rfa_0p8";
+-                      };
+-
+-                      vreg_pmu_rfa_1p2: ldo8 {
+-                              regulator-name = "vreg_pmu_rfa_1p2";
+-                      };
+-
+-                      vreg_pmu_rfa_1p7: ldo9 {
+-                              regulator-name = "vreg_pmu_rfa_1p7";
+-                      };
+-              };
+-      };
++      compatible = "asus,zenbook-a14-ux3407qa-oled", "asus,zenbook-a14-ux3407qa", "qcom,x1p42100";
+ };
+-&gpu {
+-      status = "okay";
+-};
+-
+-&gpu_zap_shader {
+-      firmware-name = "qcom/x1p42100/ASUSTeK/zenbook-a14/qcdxkmsucpurwa.mbn";
+-};
+-
+-&pcie4_port0 {
+-      wifi@0 {
+-              compatible = "pci17cb,1103";
+-              reg = <0x10000 0x0 0x0 0x0 0x0>;
+-
+-              vddaon-supply = <&vreg_pmu_aon_0p8>;
+-              vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+-              vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+-              vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+-              vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+-              vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+-              vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+-              vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+-              vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+-
+-              qcom,calibration-variant = "UX3407Q";
+-      };
+-};
+-
+-&remoteproc_adsp {
+-      firmware-name = "qcom/x1p42100/ASUSTeK/zenbook-a14/qcadsp8380.mbn",
+-                      "qcom/x1p42100/ASUSTeK/zenbook-a14/adsp_dtbs.elf";
+-
+-      status = "okay";
+-};
+-
+-&remoteproc_cdsp {
+-      firmware-name = "qcom/x1p42100/ASUSTeK/zenbook-a14/qccdsp8380.mbn",
+-                      "qcom/x1p42100/ASUSTeK/zenbook-a14/cdsp_dtbs.elf";
+-
+-      status = "okay";
+-};
+-
+-&uart14 {
+-      status = "okay";
+-
+-      bluetooth {
+-              compatible = "qcom,wcn6855-bt";
+-
+-              vddaon-supply = <&vreg_pmu_aon_0p8>;
+-              vddbtcmx-supply = <&vreg_pmu_btcmx_0p8>;
+-              vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+-              vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+-              vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+-              vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+-              vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+-              vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
++&panel {
++      compatible = "samsung,atna40ct06", "samsung,atna33xc20";
++      enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>;
+-              max-speed = <3000000>;
+-      };
++      pinctrl-0 = <&edp_bl_en>;
++      pinctrl-names = "default";
+ };
+diff --git a/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi
+new file mode 100644
+index 0000000000000..7ccb2076bab66
+--- /dev/null
++++ b/arch/arm64/boot/dts/qcom/x1p42100-asus-zenbook-a14.dtsi
+@@ -0,0 +1,138 @@
++// SPDX-License-Identifier: BSD-3-Clause
++/*
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Aleksandrs Vinarskis <alex@vinarskis.com>
++ */
++
++/dts-v1/;
++
++#include "x1p42100.dtsi"
++#include "x1-asus-zenbook-a14.dtsi"
++
++/delete-node/ &pmc8380_6;
++/delete-node/ &pmc8380_6_thermal;
++
++/ {
++      wcn6855-pmu {
++              compatible = "qcom,wcn6855-pmu";
++
++              vddaon-supply = <&vreg_wcn_0p95>;
++              vddio-supply = <&vreg_wcn_1p9>;
++              vddpcie1p3-supply = <&vreg_wcn_1p9>;
++              vddpcie1p9-supply = <&vreg_wcn_1p9>;
++              vddpmu-supply = <&vreg_wcn_0p95>;
++              vddpmucx-supply = <&vreg_wcn_0p95>;
++              vddpmumx-supply = <&vreg_wcn_0p95>;
++              vddrfa0p95-supply = <&vreg_wcn_0p95>;
++              vddrfa1p3-supply = <&vreg_wcn_1p9>;
++              vddrfa1p9-supply = <&vreg_wcn_1p9>;
++
++              bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>;
++              wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>;
++
++              pinctrl-0 = <&wcn_bt_en>, <&wcn_wlan_en>;
++              pinctrl-names = "default";
++
++              regulators {
++                      vreg_pmu_rfa_cmn_0p8: ldo0 {
++                              regulator-name = "vreg_pmu_rfa_cmn_0p8";
++                      };
++
++                      vreg_pmu_aon_0p8: ldo1 {
++                              regulator-name = "vreg_pmu_aon_0p8";
++                      };
++
++                      vreg_pmu_wlcx_0p8: ldo2 {
++                              regulator-name = "vreg_pmu_wlcx_0p8";
++                      };
++
++                      vreg_pmu_wlmx_0p8: ldo3 {
++                              regulator-name = "vreg_pmu_wlmx_0p8";
++                      };
++
++                      vreg_pmu_btcmx_0p8: ldo4 {
++                              regulator-name = "vreg_pmu_btcmx_0p8";
++                      };
++
++                      vreg_pmu_pcie_1p8: ldo5 {
++                              regulator-name = "vreg_pmu_pcie_1p8";
++                      };
++
++                      vreg_pmu_pcie_0p9: ldo6 {
++                              regulator-name = "vreg_pmu_pcie_0p9";
++                      };
++
++                      vreg_pmu_rfa_0p8: ldo7 {
++                              regulator-name = "vreg_pmu_rfa_0p8";
++                      };
++
++                      vreg_pmu_rfa_1p2: ldo8 {
++                              regulator-name = "vreg_pmu_rfa_1p2";
++                      };
++
++                      vreg_pmu_rfa_1p7: ldo9 {
++                              regulator-name = "vreg_pmu_rfa_1p7";
++                      };
++              };
++      };
++};
++
++&gpu {
++      status = "okay";
++};
++
++&gpu_zap_shader {
++      firmware-name = "qcom/x1p42100/ASUSTeK/zenbook-a14/qcdxkmsucpurwa.mbn";
++};
++
++&pcie4_port0 {
++      wifi@0 {
++              compatible = "pci17cb,1103";
++              reg = <0x10000 0x0 0x0 0x0 0x0>;
++
++              vddaon-supply = <&vreg_pmu_aon_0p8>;
++              vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
++              vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
++              vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
++              vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
++              vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
++              vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
++              vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
++              vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
++
++              qcom,calibration-variant = "UX3407Q";
++      };
++};
++
++&remoteproc_adsp {
++      firmware-name = "qcom/x1p42100/ASUSTeK/zenbook-a14/qcadsp8380.mbn",
++                      "qcom/x1p42100/ASUSTeK/zenbook-a14/adsp_dtbs.elf";
++
++      status = "okay";
++};
++
++&remoteproc_cdsp {
++      firmware-name = "qcom/x1p42100/ASUSTeK/zenbook-a14/qccdsp8380.mbn",
++                      "qcom/x1p42100/ASUSTeK/zenbook-a14/cdsp_dtbs.elf";
++
++      status = "okay";
++};
++
++&uart14 {
++      status = "okay";
++
++      bluetooth {
++              compatible = "qcom,wcn6855-bt";
++
++              vddaon-supply = <&vreg_pmu_aon_0p8>;
++              vddbtcmx-supply = <&vreg_pmu_btcmx_0p8>;
++              vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
++              vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
++              vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
++              vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
++              vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
++              vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
++
++              max-speed = <3000000>;
++      };
++};
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch b/queue-6.18/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch
new file mode 100644 (file)
index 0000000..0fa9b39
--- /dev/null
@@ -0,0 +1,45 @@
+From e305238465c6ecc7471b7f9a7eff6f0b2aa0f313 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 01:27:12 +0300
+Subject: arm64: dts: qcom: sdm850-lenovo-yoga-c630: lower PSCI cluster idle
+
+From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+
+[ Upstream commit 07db10de262f4150e24fd631a7a6c428f7bf80c9 ]
+
+With the default PSCI suspend value for cluster idle state Lenovo Yoga
+C630 isn't stable enough. For example it might reset if display device
+isn't probed early enough. Drop the bit 0x4000 from the PSCI suspend
+value to make C630 work in stable way. The bit was found by
+expertimenting with the cluster idle PSCI value. Most likely it results
+in the less deep sleep and more energy beign spent in the suspend state,
+but it's better than the non-stable system behaviour.
+
+Fixes: a1ade6cac5a2 ("arm64: dts: qcom: sdm845: Switch PSCI cpu idle states from PC to OSI")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260429-c630-fix-idle-v2-1-ac867dad6f21@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+index 90efbb7e3799b..bead957cf83b4 100644
+--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
++++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+@@ -347,6 +347,10 @@ &cdsp_pas {
+       status = "okay";
+ };
++&cluster_sleep_0 {
++      arm,psci-suspend-param = <0x41008244>;
++};
++
+ &gcc {
+       protected-clocks = <GCC_QSPI_CORE_CLK>,
+                          <GCC_QSPI_CORE_CLK_SRC>,
+-- 
+2.53.0
+
diff --git a/queue-6.18/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-6.18/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..5a76d7e
--- /dev/null
@@ -0,0 +1,52 @@
+From d0ce29b412f31047d778be95b9f5c38b0367420f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 2d24c6b3e9d9f..25bce3fe2a101 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -264,6 +264,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -285,8 +286,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch b/queue-6.18/bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch
new file mode 100644 (file)
index 0000000..1f785e0
--- /dev/null
@@ -0,0 +1,42 @@
+From 84dd0c16507dfba6d7c95eec452568121e7f6d25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 15:10:22 +0530
+Subject: bnge: Fix resource leak in bnge_init_nic() error path
+
+From: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+
+[ Upstream commit bfec39ff1484b4e9f7d93bc4580fdb634bbc7d19 ]
+
+If bnge_init_chip() fails, bnge_init_nic() jumps to err_free_ring_grps
+and returns immediately, skipping cleanup for RX ring pair buffers.
+
+Remove the early return so execution falls through to
+err_free_rx_ring_pair_bufs to properly free resources on error.
+
+Fixes: 23df6aebf803 ("bng_en: Allocate stat contexts")
+Signed-off-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+Reviewed-by: Dharmender Garg <dharmender.garg@broadcom.com>
+Reviewed-by: Rajashekar Hudumula <rajashekar.hudumula@broadcom.com>
+Link: https://patch.msgid.link/20260805094022.15487-1-bhargava.marreddy@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnge/bnge_netdev.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
+index 832eeb960bd2d..02be751f3d8fc 100644
+--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
++++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
+@@ -2154,8 +2154,6 @@ static int bnge_init_nic(struct bnge_net *bn)
+ err_free_ring_grps:
+       bnge_free_ring_grps(bn);
+-      return rc;
+-
+ err_free_rx_ring_pair_bufs:
+       bnge_free_rx_ring_pair_bufs(bn);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnge-use-int-for-bnge_fix_rings_count-return-value.patch b/queue-6.18/bnge-use-int-for-bnge_fix_rings_count-return-value.patch
new file mode 100644 (file)
index 0000000..f5c8e2c
--- /dev/null
@@ -0,0 +1,44 @@
+From 694e49b1f0eabf7010d99842845d02cb75d65d3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 03:09:20 -0700
+Subject: bnge: use int for bnge_fix_rings_count() return value
+
+From: Alok Tiwari <alok.a.tiwari@oracle.com>
+
+[ Upstream commit 2cbd8a4e5e09aa232a1f8d56ce3d070b18ab2b10 ]
+
+bnge_fix_rings_count() returns 0 on success or a negative errno on failure
+However, bnge_adjust_rings() stores its return value in a u16 variable,
+causing negative error codes such as -ENOMEM to be converted to a large
+positive value.
+
+Use an int for the return code variable so that error values are
+preserved and propagated correctly.
+
+Fixes: 627c67f038d2 ("bng_en: Add resource management support")
+Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
+Reviewed-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+Link: https://patch.msgid.link/20260801100923.1498570-1-alok.a.tiwari@oracle.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnge/bnge_resc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+index 62ebe03a0dcf3..39cc392bd8c4b 100644
+--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
++++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+@@ -151,7 +151,8 @@ static int bnge_adjust_rings(struct bnge_dev *bd, u16 *rx,
+       u16 tx_chunks = bnge_num_tx_to_cp(bd, *tx);
+       if (tx_chunks != *tx) {
+-              u16 tx_saved = tx_chunks, rc;
++              u16 tx_saved = tx_chunks;
++              int rc;
+               rc = bnge_fix_rings_count(rx, &tx_chunks, max_nq, sh);
+               if (rc)
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch b/queue-6.18/bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch
new file mode 100644 (file)
index 0000000..2a3a543
--- /dev/null
@@ -0,0 +1,54 @@
+From ee3c78709260609d7601337ef841a8ebd8da23ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:31 -0700
+Subject: bnxt: fix memory leak in bnxt_queue_mem_alloc error cases
+
+From: Will Chen <will.chen.tty@gmail.com>
+
+[ Upstream commit d1000fd7995e51deec872d154e0a40d82f7a539f ]
+
+There is a small memory leak in bnxt_queue_mem_alloc:
+when bnxt_alloc_rx_agg_bmap() succeeds
+but bnxt_alloc_one_tpa_info() later fails,
+the rx_agg_bmap allocated by bnxt_alloc_rx_agg_bmap()
+is not freed in the fallthrough cleanup cases.
+
+Free the rx_agg_bmap in the err_free_rx_agg_ring case
+and initialize clone->rx_agg_bmap = NULL earlier in the function
+to allow for safe fallthrough.
+
+Fixes: bd649c5cc958 ("bnxt_en: handle tpa_info in queue API implementation")
+Signed-off-by: Will Chen <will.chen.tty@gmail.com>
+Reviewed-by: Joe Damato <joe@dama.to>
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260729220132.1256924-1-will.chen.tty@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 52b356f4966ab..d90775c0ce0b5 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -16017,6 +16017,7 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
+       clone->rx_next_cons = 0;
+       clone->need_head_pool = false;
+       clone->rx_page_size = qcfg->rx_page_size;
++      clone->rx_agg_bmap = NULL;
+       rc = bnxt_alloc_rx_page_pool(bp, clone, rxr->page_pool->p.nid);
+       if (rc)
+@@ -16069,6 +16070,8 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
+       bnxt_free_one_tpa_info(bp, clone);
+ err_free_rx_agg_ring:
+       bnxt_free_ring(bp, &clone->rx_agg_ring_struct.ring_mem);
++      kfree(clone->rx_agg_bmap);
++      clone->rx_agg_bmap = NULL;
+ err_free_rx_ring:
+       bnxt_free_ring(bp, &clone->rx_ring_struct.ring_mem);
+ err_rxq_info_unreg:
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch b/queue-6.18/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch
new file mode 100644 (file)
index 0000000..592e562
--- /dev/null
@@ -0,0 +1,155 @@
+From 2a5bdd8f758b2323345ebbcafc622a8476a1ebc3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:34 -0700
+Subject: bnxt_en: Determine and store default RX ring in vnic structure
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 53f01cd594e223aabb538d5288e60111523c96f2 ]
+
+Each VNIC has a default RX ring.  The purpose of the default RX ring
+is to provide a destination for any packets that cannot be parsed by
+the RSS logic.  Up until now, the default RX ring is always Ring 0.
+
+We neglected to take care of this default RX ring when adding the
+queue restart feature.  If ring 0 (default ring) is re-started, it
+may now have a new FW ring ID after freeing the old one and
+allocating a new one.  The VNIC now may have a stale default ring
+and it may generate an internal exception.  This exception may
+appear in dmesg:
+
+FW reported unknown error type 10
+
+The best way to resolve this issue is to use a more appropriate
+ring for the default ring instead of always ring 0.  Ring 0 may not
+even be in the RSS table, especially on a new RSS context.
+
+This patch adds the logic to determine and store the proper default
+RX ring for a VNIC.  For an RSS VNIC, the default ring is the lowest
+ring number in the RSS table.  The next patch will add proper logic
+to update the VNIC if the default ring changes after queue restart.
+
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-3-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0b137529a899 ("bnxt_en: Refresh VNIC default ring on queue restart if needed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 33 +++++++++++++++--------
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h |  1 +
+ 2 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index fba5b7f27ce7b..df5fd228d84ae 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6593,25 +6593,36 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings)
+ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+ {
+       bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
+-      u16 i, j;
++      u16 i, j, min_j = bp->rx_nr_rings - 1;
+       if (!vnic->rss_table)
+-              return;
++              goto skip_rss_tbl;
+       /* Fill the RSS indirection table with ring group ids */
+       for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+               if (!no_rss)
+                       j = bp->rss_indir_tbl[i];
++              min_j = min(j, min_j);
+               vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]);
+       }
++
++skip_rss_tbl:
++      if (vnic->rss_table && !no_rss)
++              vnic->default_rx_ring = min_j;
++      else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
++              vnic->default_rx_ring = vnic->vnic_id - 1;
++      else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
++              vnic->default_rx_ring = bp->rx_nr_rings - 1;
++      else
++              vnic->default_rx_ring = 0;
+ }
+ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+                                   struct bnxt_vnic_info *vnic)
+ {
++      u16 tbl_size, i, min_j = bp->rx_nr_rings - 1;
+       __le16 *ring_tbl = vnic->rss_table;
+       struct bnxt_rx_ring_info *rxr;
+-      u16 tbl_size, i;
+       tbl_size = bnxt_get_rxfh_indir_size(bp->dev);
+@@ -6624,6 +6635,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+                       j = ethtool_rxfh_context_indir(vnic->rss_ctx)[i];
+               else
+                       j = bp->rss_indir_tbl[i];
++              min_j = min(j, min_j);
+               rxr = &bp->rx_ring[j];
+               ring_id = rxr->rx_ring_struct.fw_ring_id;
+@@ -6631,6 +6643,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+               ring_id = bnxt_cp_ring_for_rx(bp, rxr);
+               *ring_tbl++ = cpu_to_le16(ring_id);
+       }
++      vnic->default_rx_ring = min_j;
+ }
+ static void
+@@ -6827,8 +6840,9 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+               return rc;
+       if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+-              struct bnxt_rx_ring_info *rxr = &bp->rx_ring[0];
++              struct bnxt_rx_ring_info *rxr;
++              rxr = &bp->rx_ring[vnic->default_rx_ring];
+               req->default_rx_ring_id =
+                       cpu_to_le16(rxr->rx_ring_struct.fw_ring_id);
+               req->default_cmpl_ring_id =
+@@ -6861,13 +6875,7 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+               req->cos_rule = cpu_to_le16(0xffff);
+       }
+-      if (vnic->flags & BNXT_VNIC_RSS_FLAG)
+-              ring = 0;
+-      else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
+-              ring = vnic->vnic_id - 1;
+-      else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
+-              ring = bp->rx_nr_rings - 1;
+-
++      ring = vnic->default_rx_ring;
+       grp_idx = bp->rx_ring[ring].bnapi->index;
+       req->dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id);
+       req->lb_rule = cpu_to_le16(0xffff);
+@@ -11027,6 +11035,9 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt *bp)
+               return rc;
+       }
++      /* Setup the proper default RX ring */
++      bnxt_fill_hw_rss_tbl(bp, vnic);
++
+       rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+       if (rc) {
+               netdev_err(bp->dev, "Cannot allocate special vnic for NS2 A0: %x\n",
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 3ca989da0eb02..9d9ad2be3239b 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -1318,6 +1318,7 @@ struct bnxt_vnic_info {
+ #define BNXT_VNIC_RSSCTX_FLAG         0x40
+       struct ethtool_rxfh_context *rss_ctx;
+       u32             vnic_id;
++      u16             default_rx_ring;
+ };
+ struct bnxt_rss_ctx {
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch b/queue-6.18/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
new file mode 100644 (file)
index 0000000..b9175c9
--- /dev/null
@@ -0,0 +1,57 @@
+From aee1e001495da03a388d6b2cdfea5aa1f5007383 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:36 -0700
+Subject: bnxt_en: Disable EOP for TPA on all chips to prevent data corruption
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit c3faf548a00f4c17100cc9204746975fa46a73b9 ]
+
+EOP (End of frame padding) on the AGG ring may cause overlapping of
+zero padding at the end of one segment with the next segment's data.
+If Relaxed Ordering (RO) is enabled, the zero padding may overwrite
+valid data in the next segment and corrupt the data.  Older chips
+(P5 and older) do not automatically disable RO when EOP is enabled.
+On some ARM systems, data corruption was reported on 57508 (P5)
+chips with RO enabled.
+
+Always disable EOP on all chips on the AGG rings when TPA is enabled
+to fix the data corruption.
+
+Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 0d6b6866154ab..83ddf753b8c99 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -4506,11 +4506,14 @@ static void bnxt_init_one_rx_agg_ring_rxbd(struct bnxt *bp,
+               type = ((u32)rxr->rx_page_size << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+-              /* On P7, setting EOP will cause the chip to disable
+-               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
+-               * potentially higher performance with RO.
++              /* Disable EOP if TPA is enabled to prevent overlapping zero
++               * padding with the next segment's data.  On P7_PLUS, EOP will
++               * automatically disable Relaxed Ordering (RO) to prevent
++               * potential data corruption (and may degrade performance).  On
++               * older chips, RO will not be automatically disabled and may
++               * cause corruption.
+                */
+-              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++              if (!(bp->flags & BNXT_FLAG_TPA))
+                       type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch b/queue-6.18/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
new file mode 100644 (file)
index 0000000..6592a7a
--- /dev/null
@@ -0,0 +1,66 @@
+From aacfa2daf3d8b132e43e6eb38721d0788f8b7832 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Nov 2025 13:56:46 -0800
+Subject: bnxt_en: Do not set EOP on RX AGG BDs on 5760X chips
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit 30f253f8d9a01d532fdb7ec6c8a9d4c15fe29241 ]
+
+With End-of-Packet padding (EOP) set, the chip will disable Relaxed
+Ordering (RO) of TPA data packets.  A TPA segment with EOP set will be
+padded to the next cache boundary and can potentially overwrite the
+beginning bytes of the next TPA segment when RO is enabled on 5760X.
+To prevent that, the chip disables RO for TPA when EOP is set.
+
+To take advantge of RO and higher performance, do not set EOP on
+5760X chips when TPA is enabled.  Define a proper RX_BD_FLAGS_AGG_EOP
+constant to make it clear that we are setting EOP.
+
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20251126215648.1885936-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: d1000fd7995e ("bnxt: fix memory leak in bnxt_queue_mem_alloc error cases")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 ++++++++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 98a911eae8eac..1efd1f8776abe 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -4495,7 +4495,14 @@ static void bnxt_init_one_rx_agg_ring_rxbd(struct bnxt *bp,
+       ring->fw_ring_id = INVALID_HW_RING_ID;
+       if ((bp->flags & BNXT_FLAG_AGG_RINGS)) {
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+-                      RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
++                      RX_BD_TYPE_RX_AGG_BD;
++
++              /* On P7, setting EOP will cause the chip to disable
++               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
++               * potentially higher performance with RO.
++               */
++              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++                      type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+       }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index d55987e24ad6e..b140799f07d69 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -131,6 +131,7 @@ struct rx_bd {
+        #define RX_BD_TYPE_48B_BD_SIZE                          (2 << 4)
+        #define RX_BD_TYPE_64B_BD_SIZE                          (3 << 4)
+       #define RX_BD_FLAGS_SOP                                 (1 << 6)
++      #define RX_BD_FLAGS_AGG_EOP                             (1 << 6)
+       #define RX_BD_FLAGS_EOP                                 (1 << 7)
+       #define RX_BD_FLAGS_BUFFERS                             (3 << 8)
+        #define RX_BD_FLAGS_1_BUFFER_PACKET                     (0 << 8)
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt_en-fix-ptp-pps-setting-bug.patch b/queue-6.18/bnxt_en-fix-ptp-pps-setting-bug.patch
new file mode 100644 (file)
index 0000000..3162363
--- /dev/null
@@ -0,0 +1,54 @@
+From fbf62b5c86a648fc5a46f53081460449b32a991f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:37 -0700
+Subject: bnxt_en: Fix PTP PPS setting bug
+
+From: Keegan Freyhof <keegan.freyhof@broadcom.com>
+
+[ Upstream commit 80eaf88efec33ac77ed7726d066c4f2f932cc329 ]
+
+The existing driver logic is always turning on PTP_CLK_REQ_PPS
+regardless of the "on" parameter passed to bnxt_ptp_enable().
+During shutdown, PTP_CLK_REQ_PPS may be turned off and this
+bug will do the opposite and may trigger a PCIe PTM request TLP.
+On some systems this can trigger a PCIe AER.
+
+Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on"
+parameter.
+
+Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index 0abaa2bbe3577..44b7afe9a6f56 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -514,12 +514,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+               return rc;
+       case PTP_CLK_REQ_PPS:
+               /* Configure PHC PPS IN */
+-              rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
++              pin_id = 0;
++              if (!on)
++                      break;
++              rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+               if (rc)
+                       return rc;
+               rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
+               if (!rc)
+-                      ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
++                      ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL;
+               return rc;
+       default:
+               netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch b/queue-6.18/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch
new file mode 100644 (file)
index 0000000..45b5597
--- /dev/null
@@ -0,0 +1,75 @@
+From a1030280b63fcdac7fc9e586e7fa5ce9982f70c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:33 -0700
+Subject: bnxt_en: Move RSS table fill outside __bnxt_hwrm_vnic_set_rss()
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 1d0fc6c7ea49994b8ff50d02979d1e4207ec6c4f ]
+
+This is a refactor patch with no change in behavior.  The caller
+will now fill the RSS table before calling __bnxt_hwrm_vnic_set_rss().
+In the next patch, we'll add code to determine the default ring for
+the VNIC when we fill the RSS table.
+
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-2-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0b137529a899 ("bnxt_en: Refresh VNIC default ring on queue restart if needed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index d90775c0ce0b5..fba5b7f27ce7b 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6595,6 +6595,9 @@ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+       bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
+       u16 i, j;
++      if (!vnic->rss_table)
++              return;
++
+       /* Fill the RSS indirection table with ring group ids */
+       for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+               if (!no_rss)
+@@ -6634,13 +6637,8 @@ static void
+ __bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req,
+                        struct bnxt_vnic_info *vnic)
+ {
+-      if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+-              bnxt_fill_hw_rss_tbl_p5(bp, vnic);
+-              if (bp->flags & BNXT_FLAG_CHIP_P7)
+-                      req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
+-      } else {
+-              bnxt_fill_hw_rss_tbl(bp, vnic);
+-      }
++      if (bp->flags & BNXT_FLAG_CHIP_P7)
++              req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
+       if (bp->rss_hash_delta) {
+               req->hash_type = cpu_to_le32(bp->rss_hash_delta);
+@@ -6692,6 +6690,7 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp,
+       if (!set_rss)
+               return hwrm_req_send(bp, req);
++      bnxt_fill_hw_rss_tbl_p5(bp, vnic);
+       __bnxt_hwrm_vnic_set_rss(bp, req, vnic);
+       ring_tbl_map = vnic->rss_table_dma_addr;
+       nr_ctxs = bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings);
+@@ -10722,6 +10721,7 @@ static int __bnxt_setup_vnic(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+       }
+ skip_rss_ctx:
++      bnxt_fill_hw_rss_tbl(bp, vnic);
+       /* configure default vnic, ring grp */
+       rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+       if (rc) {
+-- 
+2.53.0
+
diff --git a/queue-6.18/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch b/queue-6.18/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch
new file mode 100644 (file)
index 0000000..0eca72a
--- /dev/null
@@ -0,0 +1,46 @@
+From 1ff9996190e57f9f4ff49d24cc8b362d75c0c39b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:35 -0700
+Subject: bnxt_en: Refresh VNIC default ring on queue restart if needed
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 0b137529a8997caf67190ca1d71ba8bbdb44fbfb ]
+
+When a queue is restarted, refresh VNIC_CFG for all VNICs whose
+default RX ring is the restarted ring.  This will eliminate this
+possible FW warning caused by a stale default ring in the VNIC:
+
+FW reported unknown error type 10
+
+Fixes: 5ac066b7b062 ("bnxt_en: Fix queue start to update vnic RSS table")
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-4-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index df5fd228d84ae..0d6b6866154ab 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -10954,6 +10954,11 @@ static int bnxt_set_vnic_mru_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic,
+                                  vnic->vnic_id, rc);
+                       return rc;
+               }
++              if (rxr_id == vnic->default_rx_ring) {
++                      rc = bnxt_hwrm_vnic_cfg(bp, vnic);
++                      if (rc)
++                              return rc;
++              }
+       }
+       vnic->mru = mru;
+       bnxt_hwrm_vnic_update(bp, vnic,
+-- 
+2.53.0
+
diff --git a/queue-6.18/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-6.18/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..e6dbfa4
--- /dev/null
@@ -0,0 +1,80 @@
+From 3b559a15596e2418c9a530f1a89502a4e11b5651 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 2d37b07c8215c..839f7482dc182 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1534,8 +1534,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1597,9 +1597,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-6.18/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-6.18/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..496136f
--- /dev/null
@@ -0,0 +1,74 @@
+From 01c95813af37e406055b7e67372ae48bd3e300e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 463455180a8e3..17c1ccff3ac20 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -14734,11 +14734,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
+@@ -14800,7 +14801,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -15764,8 +15765,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-6.18/bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch b/queue-6.18/bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch
new file mode 100644 (file)
index 0000000..942ec22
--- /dev/null
@@ -0,0 +1,59 @@
+From 9fb7974d831b5f9814d9ba0bbc74ed3df62c62d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:29 +0000
+Subject: bpf: Propagate untrusted pointer state in commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit cdf19b1b3c01791de074ce282089131026f52261 ]
+
+The untrusted PTR_TO_MEM early return skips pointer offset tracking
+because accesses go through probe-read handling. Moving it after full
+pointer-state propagation ensures scalar += untrusted_pointer leaves the
+destination as PTR_TO_MEM instead of an unrelated scalar.
+
+Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-3-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 80710cb8421ef..459ed144542cc 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -14713,13 +14713,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      /*
+-       * Accesses to untrusted PTR_TO_MEM are done through probe
+-       * instructions, hence no need to track offsets.
+-       */
+-      if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
+-              return 0;
+-
+       switch (base_type(ptr_reg->type)) {
+       case PTR_TO_CTX:
+       case PTR_TO_MAP_VALUE:
+@@ -14756,6 +14749,13 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+       if (dst_reg != ptr_reg)
+               *dst_reg = *ptr_reg;
++      /*
++       * Accesses to untrusted PTR_TO_MEM are done through probe
++       * instructions, hence no need to track offsets.
++       */
++      if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
++              return 0;
++
+       if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
+               return -EINVAL;
+-- 
+2.53.0
+
diff --git a/queue-6.18/bpf-split-check_reg_sane_offset-in-two-parts.patch b/queue-6.18/bpf-split-check_reg_sane_offset-in-two-parts.patch
new file mode 100644 (file)
index 0000000..c2cf795
--- /dev/null
@@ -0,0 +1,112 @@
+From b8e7076f524063ba4e7f374868757137f94e065a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Feb 2026 13:34:21 -0800
+Subject: bpf: split check_reg_sane_offset() in two parts
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit ed20a14309e09216d1fa86e12b1578fa822119b4 ]
+
+check_reg_sane_offset() is used when verifying operations like:
+
+  dst_reg += src_reg
+  ^          ^
+  |          '-------- scalar
+  '------------------- pointer
+
+To verify range for both dst_reg and src_reg. Split it in two parts:
+- one to check a pointer offset
+- another to check scalar offset
+
+This would be useful for further refactoring.
+
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20260212-ptrs-off-migration-v2-1-00820e4d3438@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Stable-dep-of: cdf19b1b3c01 ("bpf: Propagate untrusted pointer state in commuted arithmetic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 39 +++++++++++++++++++++++++++------------
+ 1 file changed, 27 insertions(+), 12 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 17c1ccff3ac20..80710cb8421ef 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -14291,9 +14291,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+       return 0;
+ }
+-static bool check_reg_sane_offset(struct bpf_verifier_env *env,
+-                                const struct bpf_reg_state *reg,
+-                                enum bpf_reg_type type)
++static bool check_reg_sane_offset_scalar(struct bpf_verifier_env *env,
++                                       const struct bpf_reg_state *reg,
++                                       enum bpf_reg_type type)
+ {
+       bool known = tnum_is_const(reg->var_off);
+       s64 val = reg->var_off.value;
+@@ -14305,12 +14305,6 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env,
+               return false;
+       }
+-      if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
+-              verbose(env, "%s pointer offset %d is not allowed\n",
+-                      reg_type_str(env, type), reg->off);
+-              return false;
+-      }
+-
+       if (smin == S64_MIN) {
+               verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n",
+                       reg_type_str(env, type));
+@@ -14326,6 +14320,27 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env,
+       return true;
+ }
++static bool check_reg_sane_offset_ptr(struct bpf_verifier_env *env,
++                                    const struct bpf_reg_state *reg,
++                                    enum bpf_reg_type type)
++{
++      s64 smin = reg->smin_value;
++
++      if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
++              verbose(env, "%s pointer offset %d is not allowed\n",
++                      reg_type_str(env, type), reg->off);
++              return false;
++      }
++
++      if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
++              verbose(env, "%s pointer offset %lld is not allowed\n",
++                      reg_type_str(env, type), smin);
++              return false;
++      }
++
++      return true;
++}
++
+ enum {
+       REASON_BOUNDS   = -1,
+       REASON_TYPE     = -2,
+@@ -14741,8 +14756,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+       if (dst_reg != ptr_reg)
+               *dst_reg = *ptr_reg;
+-      if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+-          !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
++      if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
++          !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
+               return -EINVAL;
+       /* pointer types do not carry 32-bit bounds at the moment. */
+@@ -14871,7 +14886,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
++      if (!check_reg_sane_offset_ptr(env, dst_reg, ptr_reg->type))
+               return -EINVAL;
+       reg_bounds_sync(dst_reg);
+       bounds_ret = sanitize_check_bounds(env, insn, dst_reg);
+-- 
+2.53.0
+
diff --git a/queue-6.18/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch b/queue-6.18/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
new file mode 100644 (file)
index 0000000..079eb47
--- /dev/null
@@ -0,0 +1,170 @@
+From ccb35938773815882e066696dbda415f1d0f0d2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:32:47 +0000
+Subject: bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()
+
+From: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+
+[ Upstream commit e5fd3f514e27db1f05fbd72ba615d74941e23c51 ]
+
+reqsk_queue_hash_req() publishes a TCP_NEW_SYN_RECV request_sock onto
+the ehash chain, drops the bucket lock, and only afterwards sets
+rsk_refcnt to 3.
+
+Lockless readers such as __inet_lookup_established() handle this with
+refcount_inc_not_zero(), but bpf_iter_tcp_established_batch() uses plain
+sock_hold() while holding the bucket lock, on the assumption that the
+lock guarantees sk_refcnt > 0. That assumption does not hold for
+request_sock:
+
+  CPU 0                                CPU 1
+  -----                                -----
+  tcp_conn_request()
+   reqsk_queue_hash_req()
+    inet_ehash_insert(req)
+     spin_lock(bucket)
+     __sk_nulls_add_node_rcu(req)      // rsk_refcnt == 0
+     spin_unlock(bucket)
+                                       bpf_iter_tcp_established_batch()
+                                        spin_lock(bucket)
+                                        sock_hold(req)   <-- addition on 0
+                                        spin_unlock(bucket)
+    refcount_set(&req->rsk_refcnt, 3)  // clobbers saturated value
+
+which surfaces as:
+
+  refcount_t: addition on 0; use-after-free.
+  WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x48/0x90, CPU#1
+  Call Trace:
+   bpf_iter_tcp_established_batch+0x14e/0x170
+   bpf_iter_tcp_batch+0x53/0x200
+   bpf_iter_tcp_seq_next+0x27/0x70
+   bpf_seq_read+0x107/0x410
+   vfs_read+0xb9/0x380
+
+The iterator's stolen reference is lost when the publishing CPU's
+refcount_set() overwrites the count, leaving the socket one reference
+short. When the last legitimate owner drops its reference the reqsk is
+freed while still reachable, leading to use-after-free.
+
+This reproduces in seconds with tcp_syncookies=0, a handful of threads
+doing connect()/close() to a local listener while others read an
+iter/tcp link in a tight loop.
+
+Use refcount_inc_not_zero() and skip the socket on failure. A skipped
+socket is still part of the bucket, so keep counting it in expected.
+The reallocations are sized from expected, and a request sock whose
+refcount gets published while the lock is held across the last realloc
+must already have room.
+
+A skipped socket is counted in expected but never batched, so end_sk
+can be short of expected on a batch that is actually complete. Decide
+completeness by whether the walk left any socket behind instead. The
+WARN after the locked realloc checks the same, replacing an
+end_sk == expected check that could not hold on that path since
+commit cdec67a489d4 ("bpf: tcp: Make sure iter->batch always
+contains a full bucket snapshot").
+
+If every matching socket in a bucket is mid-init (refcount 0), end_sk
+stays 0. Advance to the next bucket rather than returning a batch entry
+that was never filled this round.
+
+Fixes: 04c7820b776f ("bpf: tcp: Bpf iter batching and lock_sock")
+Assisted-by: Claude:unspecified
+Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://lore.kernel.org/bpf/20260730-bpf-iter-tcp-refcnt-v3-1-754b9c8a6717@linux.dev
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 43 ++++++++++++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 19 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 3463e5b964a98..708b69cc2f56c 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -3219,24 +3219,24 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+ {
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct hlist_nulls_node *node;
+-      unsigned int expected = 1;
+-      struct sock *sk;
+-
+-      sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++].sk = *start_sk;
++      struct sock *sk = *start_sk;
++      unsigned int expected = 0;
+-      sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+-              if (seq_sk_match(seq, sk)) {
+-                      if (iter->end_sk < iter->max_sk) {
+-                              sock_hold(sk);
+-                              iter->batch[iter->end_sk++].sk = sk;
+-                      } else if (!*start_sk) {
+-                              /* Remember where we left off. */
+-                              *start_sk = sk;
+-                      }
+-                      expected++;
++              if (!seq_sk_match(seq, sk))
++                      continue;
++              expected++;
++              if (iter->end_sk < iter->max_sk) {
++                      /* reqsk_queue_hash_req() inserts with sk_refcnt == 0
++                       * and refcount_set()s it after the bucket lock drops.
++                       */
++                      if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
++                              continue;
++                      iter->batch[iter->end_sk++].sk = sk;
++              } else if (!*start_sk) {
++                      /* Remember where we left off. */
++                      *start_sk = sk;
+               }
+       }
+@@ -3274,12 +3274,13 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       struct sock *sk;
+       int err;
++again:
+       sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was too small. */
+@@ -3298,7 +3299,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was still too small. Hold onto the lock while we try
+@@ -3311,10 +3312,14 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return ERR_PTR(err);
+       }
+-      expected = bpf_iter_fill_batch(seq, &sk);
+-      WARN_ON_ONCE(iter->end_sk != expected);
++      bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(sk);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
++      if (unlikely(!iter->end_sk)) {
++              ++iter->state.bucket;
++              goto again;
++      }
+       return iter->batch[0].sk;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch b/queue-6.18/btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch
new file mode 100644 (file)
index 0000000..3292421
--- /dev/null
@@ -0,0 +1,67 @@
+From 9b2b7318df597191bf84329f5e6e74a56cb73d0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 16:37:39 +0930
+Subject: btrfs: disable bs > ps support if no transparent hugepage support
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 4c375ac546ea667e619ab77d34cca6edcab7c448 ]
+
+Btrfs relies on mapping_set_folio_order_range() to set the minimal
+folio order for all its data inodes, but that function will be no-op if
+transparent hugepage is not enabled.
+
+Guard the bs > ps support behind CONFIG_TRANSPARENT_HUGEPAGE, just like
+all other filesystems.
+
+Fixes: 98077f7f2180 ("btrfs: enable experimental bs > ps support")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/Kconfig |  3 ++-
+ fs/btrfs/fs.c    | 12 ++++++++++--
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
+index 4bafbf6636cd2..5f922563b6b62 100644
+--- a/fs/btrfs/Kconfig
++++ b/fs/btrfs/Kconfig
+@@ -115,7 +115,8 @@ config BTRFS_EXPERIMENTAL
+         - extent tree v2 - complex rework of extent tracking
+-        - block size > page size support
++        - block size > page size support - needs transparent huge page and
++                                           non-HIGHMEM system
+         - shutdown ioctl and auto-degradation support
+diff --git a/fs/btrfs/fs.c b/fs/btrfs/fs.c
+index feb0a2faa8379..bf86d8d5a05d9 100644
+--- a/fs/btrfs/fs.c
++++ b/fs/btrfs/fs.c
+@@ -94,9 +94,17 @@ bool __attribute_const__ btrfs_supported_blocksize(u32 blocksize)
+        *
+        * Considering HIGHMEM is such a pain to deal with and it's going
+        * to be deprecated eventually, just reject HIGHMEM && bs > ps cases.
++       *
++       * Finally, for bs > ps cases, we need to set the minimal folio order,
++       * which requires transparent hugepage.
+        */
+-      if (IS_ENABLED(CONFIG_HIGHMEM) && blocksize > PAGE_SIZE)
+-              return false;
++      if (blocksize > PAGE_SIZE) {
++              if (IS_ENABLED(CONFIG_HIGHMEM))
++                      return false;
++
++              if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
++                      return false;
++      }
+       return true;
+ #endif
+       return false;
+-- 
+2.53.0
+
diff --git a/queue-6.18/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch b/queue-6.18/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
new file mode 100644 (file)
index 0000000..eaefa74
--- /dev/null
@@ -0,0 +1,96 @@
+From edcab8276b4fe316fe5c1e52c8c15ec4636fe137 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 14:53:52 +0300
+Subject: btrfs: fix memory leak in btrfs_do_encoded_write()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit d2a4e4e626b2f4670b69b430c357f03f53eb6632 ]
+
+Local fuzzing of 6.12.94 has found the following memory leak:
+
+Unreferenced object 0xffff888018050a80 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 10 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
+    10 0a 05 18 80 88 ff ff 10 0a 05 18 80 88 ff ff  ................
+  backtrace (crc a8a6fc29):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    extent_changeset_alloc fs/btrfs/extent_io.h:207 [inline]
+    qgroup_reserve_data+0x1c5/0x7d0 fs/btrfs/qgroup.c:4305
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Unreferenced object 0xffff888018050a00 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 ff 0f 00 00 00 00 00 00  ................
+    90 0a 05 18 80 88 ff ff 90 0a 05 18 80 88 ff ff  ................
+  backtrace (crc cb5c9580):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    kzalloc_noprof include/linux/slab.h:1014 [inline]
+    ulist_prealloc+0x9c/0x110 fs/btrfs/ulist.c:114
+    extent_changeset_prealloc fs/btrfs/extent_io.h:217 [inline]
+    __set_extent_bit+0x16b/0x1a70 fs/btrfs/extent-io-tree.c:1086
+    set_record_extent_bits+0x50/0x90 fs/btrfs/extent-io-tree.c:1821
+    qgroup_reserve_data+0x274/0x7d0 fs/btrfs/qgroup.c:4312
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fix this by freeing an extent changeset before returning from
+btrfs_do_encoded_write().
+
+Fixes: 7c0c7269f7b5 ("btrfs: add BTRFS_IOC_ENCODED_WRITE")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 36f75c6a8344d..7af5ea0cf55fd 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -10037,6 +10037,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
+       }
+       kvfree(folios);
+ out:
++      extent_changeset_free(data_reserved);
+       if (ret >= 0)
+               iocb->ki_pos += encoded->len;
+       return ret;
+-- 
+2.53.0
+
diff --git a/queue-6.18/btrfs-move-large-data-folios-out-of-experimental-fea.patch b/queue-6.18/btrfs-move-large-data-folios-out-of-experimental-fea.patch
new file mode 100644 (file)
index 0000000..21c9a37
--- /dev/null
@@ -0,0 +1,96 @@
+From edd1fee37171e82730173367ff9ae8cfc44a8296 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Apr 2026 10:20:25 +0930
+Subject: btrfs: move large data folios out of experimental features
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 9bce95edb1b4d2802de9273b5170bfcff3090d24 ]
+
+This feature was introduced in v6.17 under experimental, and we had
+several small bugs related to or exposed by that:
+
+  e9e3b22ddfa7 ("btrfs: fix beyond-EOF write handling")
+  18de34daa7c6 ("btrfs: truncate ordered extent when skipping writeback past i_size")
+
+Otherwise, the feature has been frequently tested by btrfs developers.
+
+The latest fix only arrived in v6.19. After three releases, I think it's
+time to move this feature out of experimental.
+
+And since we're here, also remove the comment about the bitmap size
+limit, which is no longer relevant in the context. It will soon be
+outdated for the incoming huge folio support.
+
+Reviewed-by: Neal Gompa <neal@gompa.dev>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 4c375ac546ea ("btrfs: disable bs > ps support if no transparent hugepage support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/Kconfig       |  2 +-
+ fs/btrfs/btrfs_inode.h |  3 ---
+ fs/btrfs/defrag.c      | 17 -----------------
+ 3 files changed, 1 insertion(+), 21 deletions(-)
+
+diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
+index 6d6fc85835d46..4bafbf6636cd2 100644
+--- a/fs/btrfs/Kconfig
++++ b/fs/btrfs/Kconfig
+@@ -115,7 +115,7 @@ config BTRFS_EXPERIMENTAL
+         - extent tree v2 - complex rework of extent tracking
+-        - large folio and block size (> page size) support
++        - block size > page size support
+         - shutdown ioctl and auto-degradation support
+diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
+index b6b46f951f11a..7a647d42d181c 100644
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -535,12 +535,9 @@ static inline void btrfs_set_inode_mapping_order(struct btrfs_inode *inode)
+       /* Metadata inode should not reach here. */
+       ASSERT(is_data_inode(inode));
+-      /* We only allow BITS_PER_LONGS blocks for each bitmap. */
+-#ifdef CONFIG_BTRFS_EXPERIMENTAL
+       mapping_set_folio_order_range(inode->vfs_inode.i_mapping,
+                                     inode->root->fs_info->block_min_order,
+                                     inode->root->fs_info->block_max_order);
+-#endif
+ }
+ /* Array of bytes with variable length, hexadecimal format 0x1234 */
+diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
+index 2e3c011d410a6..a47dc6b9d33ff 100644
+--- a/fs/btrfs/defrag.c
++++ b/fs/btrfs/defrag.c
+@@ -862,23 +862,6 @@ static struct folio *defrag_prepare_one_folio(struct btrfs_inode *inode, pgoff_t
+       if (IS_ERR(folio))
+               return folio;
+-      /*
+-       * Since we can defragment files opened read-only, we can encounter
+-       * transparent huge pages here (see CONFIG_READ_ONLY_THP_FOR_FS).
+-       *
+-       * The IO for such large folios is not fully tested, thus return
+-       * an error to reject such folios unless it's an experimental build.
+-       *
+-       * Filesystem transparent huge pages are typically only used for
+-       * executables that explicitly enable them, so this isn't very
+-       * restrictive.
+-       */
+-      if (!IS_ENABLED(CONFIG_BTRFS_EXPERIMENTAL) && folio_test_large(folio)) {
+-              folio_unlock(folio);
+-              folio_put(folio);
+-              return ERR_PTR(-ETXTBSY);
+-      }
+-
+       ret = set_folio_extent_mapped(folio);
+       if (ret < 0) {
+               folio_unlock(folio);
+-- 
+2.53.0
+
diff --git a/queue-6.18/btrfs-update-the-kconfig-string-for-config_btrfs_exp.patch b/queue-6.18/btrfs-update-the-kconfig-string-for-config_btrfs_exp.patch
new file mode 100644 (file)
index 0000000..e712867
--- /dev/null
@@ -0,0 +1,46 @@
+From 712ac69e62af09ee2c9d66ae8c196713d1583fbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jan 2026 14:01:14 +1030
+Subject: btrfs: update the Kconfig string for CONFIG_BTRFS_EXPERIMENTAL
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 64dd1caf88f96146edee24e82834cf2a11c3932b ]
+
+The following new features are missing:
+
+- Async checksum
+
+- Shutdown ioctl and auto-degradation
+
+- Larger block size support
+  Which is dependent on larger folios.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 4c375ac546ea ("btrfs: disable bs > ps support if no transparent hugepage support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/Kconfig | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
+index 4438637c8900c..6d6fc85835d46 100644
+--- a/fs/btrfs/Kconfig
++++ b/fs/btrfs/Kconfig
+@@ -115,6 +115,10 @@ config BTRFS_EXPERIMENTAL
+         - extent tree v2 - complex rework of extent tracking
+-        - large folio support
++        - large folio and block size (> page size) support
++
++        - shutdown ioctl and auto-degradation support
++
++        - asynchronous checksum generation for data writes
+         If unsure, say N.
+-- 
+2.53.0
+
diff --git a/queue-6.18/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-6.18/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..b6ab6ad
--- /dev/null
@@ -0,0 +1,70 @@
+From 4ffa634392b99b5d073f4e33073160b27cdf927b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 19d457ae4c3bb..e53a8390756b7 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -483,7 +483,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
+@@ -517,7 +517,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-6.18/devlink-fix-net-namespace-reference-leak-in-reload.patch b/queue-6.18/devlink-fix-net-namespace-reference-leak-in-reload.patch
new file mode 100644 (file)
index 0000000..0a6abd9
--- /dev/null
@@ -0,0 +1,42 @@
+From cc145e70baf7a1cdaf437fb3dc4a5fb51ed45e41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:06:00 +0300
+Subject: devlink: fix net namespace reference leak in reload
+
+From: Or Har-Toov <ohartoov@nvidia.com>
+
+[ Upstream commit 1c4dac9bf1d2ac31da63b794bdec697777cbd0fd ]
+
+devlink_nl_reload_doit() calls devlink_netns_get(), which returns a net
+with a held reference. When the requested namespace differs from the
+current one and the reload action is not DRIVER_REINIT, the function
+returns -EOPNOTSUPP without releasing the reference. Add the missing
+put_net() on this error path.
+
+Fixes: 2edd92570441 ("devlink: don't allow to change net namespace for FW_ACTIVATE reload action")
+Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260729080600.2427721-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/dev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/devlink/dev.c b/net/devlink/dev.c
+index 02602704bdeaa..ed442c1bed8db 100644
+--- a/net/devlink/dev.c
++++ b/net/devlink/dev.c
+@@ -577,6 +577,7 @@ int devlink_nl_reload_doit(struct sk_buff *skb, struct genl_info *info)
+                   action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Changing namespace is only supported for reinit action");
++                      put_net(dest_net);
+                       return -EOPNOTSUPP;
+               }
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch b/queue-6.18/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
new file mode 100644 (file)
index 0000000..69f5a7f
--- /dev/null
@@ -0,0 +1,79 @@
+From e3855d2b96d64b35e4fc56c3e25f1c23738f197a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:38:06 +0800
+Subject: drm/bridge: ps8640: propagate AUX transfer register errors
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 20697ecb299cd77b4cf8b28f655e56606b0472d8 ]
+
+ps8640_aux_transfer_msg() programs the AUX address registers, starts the
+AUX transfer, waits for SWAUX_SEND to clear, and reads the AUX status
+register. Several of those regmap operations have return values, but the
+function only checks a stale ret after the status read.
+
+Propagate failures from the address write, transfer start, completion
+poll, and status read. This avoids returning a transfer length when the
+bridge register transaction or AUX completion wait failed.
+
+Fixes: 13afcdd7277e ("drm/bridge: parade-ps8640: Add support for AUX channel")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patch.msgid.link/20260723103509.2-ps8640-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/parade-ps8640.c | 27 ++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
+index 825777a5758f6..db8e5889dc7f1 100644
+--- a/drivers/gpu/drm/bridge/parade-ps8640.c
++++ b/drivers/gpu/drm/bridge/parade-ps8640.c
+@@ -257,8 +257,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+       addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD :
+                                             ((len - 1) & SWAUX_LENGTH_MASK);
+-      regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
+-                        ARRAY_SIZE(addr_len));
++      ret = regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
++                              ARRAY_SIZE(addr_len));
++      if (ret) {
++              DRM_DEV_ERROR(dev,
++                            "failed to write AUX address %#x, len %zu: %d\n",
++                            msg->address, len, ret);
++              return ret;
++      }
+       if (len && (request == DP_AUX_NATIVE_WRITE ||
+                   request == DP_AUX_I2C_WRITE)) {
+@@ -274,13 +280,22 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+               }
+       }
+-      regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      ret = regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to start AUX transfer: %d\n", ret);
++              return ret;
++      }
+       /* Zero delay loop because i2c transactions are slow already */
+-      regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
+-                               !(data & SWAUX_SEND), 0, 50 * 1000);
++      ret = regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
++                                     !(data & SWAUX_SEND), 0, 50 * 1000);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to complete AUX transfer: %d\n",
++                            ret);
++              return ret;
++      }
+-      regmap_read(map, PAGE0_SWAUX_STATUS, &data);
++      ret = regmap_read(map, PAGE0_SWAUX_STATUS, &data);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n",
+                             ret);
+-- 
+2.53.0
+
diff --git a/queue-6.18/drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch b/queue-6.18/drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch
new file mode 100644 (file)
index 0000000..05386db
--- /dev/null
@@ -0,0 +1,63 @@
+From 1865e71f3fb4885f01ec3ba8c92281d8bde935c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jul 2026 09:59:45 +0200
+Subject: drm/xe/uc: Apply RCS/CCS yield policy to SR-IOV VFs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
+
+[ Upstream commit d1643db3b037b57f2af7f85c3821d6fe69c492f6 ]
+
+VFs were missing the call to apply the global scheduling policy.
+Call xe_guc_submit_enable() during vf_uc_load_hw() to ensure VFs
+get the same policy enforcement as PF.
+
+Fixes: 26caeae9fb48 ("drm/xe/guc: Set RCS/CCS yield policy")
+Suggested-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
+Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Link: https://patch.msgid.link/20260709075945.1337660-1-marcin.bernatowicz@linux.intel.com
+Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
+(cherry picked from commit f09360e857130f7ab7f069e2421e6b4a6e502531)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_uc.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
+index 465bda3554439..b799efc838017 100644
+--- a/drivers/gpu/drm/xe/xe_uc.c
++++ b/drivers/gpu/drm/xe/xe_uc.c
+@@ -15,6 +15,7 @@
+ #include "xe_guc.h"
+ #include "xe_guc_pc.h"
+ #include "xe_guc_engine_activity.h"
++#include "xe_guc_submit.h"
+ #include "xe_huc.h"
+ #include "xe_sriov.h"
+ #include "xe_uc_fw.h"
+@@ -160,12 +161,14 @@ static int vf_uc_load_hw(struct xe_uc *uc)
+       if (err)
+               goto err_out;
+-      uc->guc.submission_state.enabled = true;
+-
+       err = xe_guc_opt_in_features_enable(&uc->guc);
+       if (err)
+               goto err_out;
++      err = xe_guc_submit_enable(&uc->guc);
++      if (err)
++              return err;
++
+       err = xe_gt_record_default_lrcs(uc_to_gt(uc));
+       if (err)
+               goto err_out;
+-- 
+2.53.0
+
diff --git a/queue-6.18/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch b/queue-6.18/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch
new file mode 100644 (file)
index 0000000..5eacb19
--- /dev/null
@@ -0,0 +1,49 @@
+From f411b21abd65a052fdac454837fb4120d4276142 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 23:26:30 -0700
+Subject: enic: fix tx_hang_reset use-after-free on device removal
+
+From: Satish Kharat <satishkh@cisco.com>
+
+[ Upstream commit ec680ea4ba1bca92a767fb7e7869758bfdd886e3 ]
+
+enic_remove() cancels the reset and change_mtu_work items but does not
+cancel tx_hang_reset. A TX timeout that fires while the device is being
+removed can schedule enic_tx_hang_reset() so that it runs after
+free_netdev(), resulting in a use-after-free.
+
+cancel_work_sync() alone is not sufficient here: the still-live watchdog
+and notify paths can re-schedule these work items in the window between
+the cancel and unregister_netdev(). Use disable_work_sync(), which
+cancels the work and blocks any subsequent schedule_work() from
+requeuing it, and apply it to the reset and change_mtu_work items as
+well so the same requeue race is closed for all teardown work.
+
+Fixes: 937317c7c109 ("enic: do hang reset only in case of tx timeout")
+Signed-off-by: Satish Kharat <satishkh@cisco.com>
+Link: https://patch.msgid.link/20260728062730.2394873-1-satishkh@cisco.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/cisco/enic/enic_main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
+index 6bc8dfdb3d4be..2a8b41d8eb883 100644
+--- a/drivers/net/ethernet/cisco/enic/enic_main.c
++++ b/drivers/net/ethernet/cisco/enic/enic_main.c
+@@ -2959,8 +2959,9 @@ static void enic_remove(struct pci_dev *pdev)
+       if (netdev) {
+               struct enic *enic = netdev_priv(netdev);
+-              cancel_work_sync(&enic->reset);
+-              cancel_work_sync(&enic->change_mtu_work);
++              disable_work_sync(&enic->reset);
++              disable_work_sync(&enic->tx_hang_reset);
++              disable_work_sync(&enic->change_mtu_work);
+               unregister_netdev(netdev);
+               enic_dev_deinit(enic);
+               vnic_dev_close(enic->vdev);
+-- 
+2.53.0
+
diff --git a/queue-6.18/eth-bnxt-store-rx-buffer-size-per-queue.patch b/queue-6.18/eth-bnxt-store-rx-buffer-size-per-queue.patch
new file mode 100644 (file)
index 0000000..c455648
--- /dev/null
@@ -0,0 +1,310 @@
+From 38ccb00a12bf489e36975ecc880f154886b60d39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 15:28:11 -0700
+Subject: eth: bnxt: store rx buffer size per queue
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit f57efb32aae1da5c0a25acf473ef4ab559894adf ]
+
+Instead of using a constant buffer length, allow configuring the size
+for each queue separately. There is no way to change the length yet, and
+it'll be passed from memory providers in a later patch.
+
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Stable-dep-of: d1000fd7995e ("bnxt: fix memory leak in bnxt_queue_mem_alloc error cases")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 56 +++++++++++--------
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  1 +
+ drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |  6 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  2 +-
+ 4 files changed, 38 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index f3fbbf188053c..fddfdf807950f 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -905,7 +905,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
+ static bool bnxt_separate_head_pool(struct bnxt_rx_ring_info *rxr)
+ {
+-      return rxr->need_head_pool || PAGE_SIZE > BNXT_RX_PAGE_SIZE;
++      return rxr->need_head_pool || rxr->rx_page_size < PAGE_SIZE;
+ }
+ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
+@@ -915,9 +915,9 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
+ {
+       struct page *page;
+-      if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) {
++      if (rxr->rx_page_size < PAGE_SIZE) {
+               page = page_pool_dev_alloc_frag(rxr->page_pool, offset,
+-                                              BNXT_RX_PAGE_SIZE);
++                                              rxr->rx_page_size);
+       } else {
+               page = page_pool_dev_alloc_pages(rxr->page_pool);
+               *offset = 0;
+@@ -936,8 +936,9 @@ static netmem_ref __bnxt_alloc_rx_netmem(struct bnxt *bp, dma_addr_t *mapping,
+ {
+       netmem_ref netmem;
+-      if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) {
+-              netmem = page_pool_alloc_frag_netmem(rxr->page_pool, offset, BNXT_RX_PAGE_SIZE, gfp);
++      if (rxr->rx_page_size < PAGE_SIZE) {
++              netmem = page_pool_alloc_frag_netmem(rxr->page_pool, offset,
++                                                   rxr->rx_page_size, gfp);
+       } else {
+               netmem = page_pool_alloc_netmems(rxr->page_pool, gfp);
+               *offset = 0;
+@@ -1155,9 +1156,9 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
+               return NULL;
+       }
+       dma_addr -= bp->rx_dma_offset;
+-      dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
++      dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, rxr->rx_page_size,
+                               bp->rx_dir);
+-      skb = napi_build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE);
++      skb = napi_build_skb(data_ptr - bp->rx_offset, rxr->rx_page_size);
+       if (!skb) {
+               page_pool_recycle_direct(rxr->page_pool, page);
+               return NULL;
+@@ -1189,7 +1190,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
+               return NULL;
+       }
+       dma_addr -= bp->rx_dma_offset;
+-      dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
++      dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, rxr->rx_page_size,
+                               bp->rx_dir);
+       if (unlikely(!payload))
+@@ -1203,7 +1204,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
+       skb_mark_for_recycle(skb);
+       off = (void *)data_ptr - page_address(page);
+-      skb_add_rx_frag(skb, 0, page, off, len, BNXT_RX_PAGE_SIZE);
++      skb_add_rx_frag(skb, 0, page, off, len, rxr->rx_page_size);
+       memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN,
+              payload + NET_IP_ALIGN);
+@@ -1288,7 +1289,7 @@ static u32 __bnxt_rx_agg_netmems(struct bnxt *bp,
+               if (skb) {
+                       skb_add_rx_frag_netmem(skb, i, cons_rx_buf->netmem,
+                                              cons_rx_buf->offset,
+-                                             frag_len, BNXT_RX_PAGE_SIZE);
++                                             frag_len, rxr->rx_page_size);
+               } else {
+                       skb_frag_t *frag = &shinfo->frags[i];
+@@ -1313,7 +1314,7 @@ static u32 __bnxt_rx_agg_netmems(struct bnxt *bp,
+                       if (skb) {
+                               skb->len -= frag_len;
+                               skb->data_len -= frag_len;
+-                              skb->truesize -= BNXT_RX_PAGE_SIZE;
++                              skb->truesize -= rxr->rx_page_size;
+                       }
+                       --shinfo->nr_frags;
+@@ -1328,7 +1329,7 @@ static u32 __bnxt_rx_agg_netmems(struct bnxt *bp,
+               }
+               page_pool_dma_sync_netmem_for_cpu(rxr->page_pool, netmem, 0,
+-                                                BNXT_RX_PAGE_SIZE);
++                                                rxr->rx_page_size);
+               total_frag_len += frag_len;
+               prod = NEXT_RX_AGG(prod);
+@@ -2295,8 +2296,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+                       if (!skb)
+                               goto oom_next_rx;
+               } else {
+-                      skb = bnxt_xdp_build_skb(bp, skb, agg_bufs,
+-                                               rxr->page_pool, &xdp);
++                      skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr, &xdp);
+                       if (!skb) {
+                               /* we should be able to free the old skb here */
+                               bnxt_xdp_buff_frags_free(rxr, &xdp);
+@@ -3844,11 +3844,13 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
+       pp.pool_size = bp->rx_agg_ring_size / agg_size_fac;
+       if (BNXT_RX_PAGE_MODE(bp))
+               pp.pool_size += bp->rx_ring_size / rx_size_fac;
++
++      pp.order = get_order(rxr->rx_page_size);
+       pp.nid = numa_node;
+       pp.netdev = bp->dev;
+       pp.dev = &bp->pdev->dev;
+       pp.dma_dir = bp->rx_dir;
+-      pp.max_len = PAGE_SIZE;
++      pp.max_len = PAGE_SIZE << pp.order;
+       pp.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV |
+                  PP_FLAG_ALLOW_UNREADABLE_NETMEM;
+       pp.queue_idx = rxr->bnapi->index;
+@@ -3859,7 +3861,10 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
+       rxr->page_pool = pool;
+       rxr->need_head_pool = page_pool_is_unreadable(pool);
++      rxr->need_head_pool |= !!pp.order;
+       if (bnxt_separate_head_pool(rxr)) {
++              pp.order = 0;
++              pp.max_len = PAGE_SIZE;
+               pp.pool_size = min(bp->rx_ring_size / rx_size_fac, 1024);
+               pp.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
+               pool = page_pool_create(&pp);
+@@ -4335,6 +4340,8 @@ static void bnxt_init_ring_struct(struct bnxt *bp)
+               if (!rxr)
+                       goto skip_rx;
++              rxr->rx_page_size = BNXT_RX_PAGE_SIZE;
++
+               ring = &rxr->rx_ring_struct;
+               rmem = &ring->ring_mem;
+               rmem->nr_pages = bp->rx_nr_pages;
+@@ -4494,7 +4501,7 @@ static void bnxt_init_one_rx_agg_ring_rxbd(struct bnxt *bp,
+       ring = &rxr->rx_agg_ring_struct;
+       ring->fw_ring_id = INVALID_HW_RING_ID;
+       if ((bp->flags & BNXT_FLAG_AGG_RINGS)) {
+-              type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
++              type = ((u32)rxr->rx_page_size << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+               /* On P7, setting EOP will cause the chip to disable
+@@ -7071,6 +7078,7 @@ static void bnxt_hwrm_ring_grp_free(struct bnxt *bp)
+ static void bnxt_set_rx_ring_params_p5(struct bnxt *bp, u32 ring_type,
+                                      struct hwrm_ring_alloc_input *req,
++                                     struct bnxt_rx_ring_info *rxr,
+                                      struct bnxt_ring_struct *ring)
+ {
+       struct bnxt_ring_grp_info *grp_info = &bp->grp_info[ring->grp_idx];
+@@ -7080,7 +7088,7 @@ static void bnxt_set_rx_ring_params_p5(struct bnxt *bp, u32 ring_type,
+       if (ring_type == HWRM_RING_ALLOC_AGG) {
+               req->ring_type = RING_ALLOC_REQ_RING_TYPE_RX_AGG;
+               req->rx_ring_id = cpu_to_le16(grp_info->rx_fw_ring_id);
+-              req->rx_buf_size = cpu_to_le16(BNXT_RX_PAGE_SIZE);
++              req->rx_buf_size = cpu_to_le16(rxr->rx_page_size);
+               enables |= RING_ALLOC_REQ_ENABLES_RX_RING_ID_VALID;
+       } else {
+               req->rx_buf_size = cpu_to_le16(bp->rx_buf_use_size);
+@@ -7094,6 +7102,7 @@ static void bnxt_set_rx_ring_params_p5(struct bnxt *bp, u32 ring_type,
+ }
+ static int hwrm_ring_alloc_send_msg(struct bnxt *bp,
++                                  struct bnxt_rx_ring_info *rxr,
+                                   struct bnxt_ring_struct *ring,
+                                   u32 ring_type, u32 map_index)
+ {
+@@ -7150,7 +7159,8 @@ static int hwrm_ring_alloc_send_msg(struct bnxt *bp,
+                             cpu_to_le32(bp->rx_ring_mask + 1) :
+                             cpu_to_le32(bp->rx_agg_ring_mask + 1);
+               if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS)
+-                      bnxt_set_rx_ring_params_p5(bp, ring_type, req, ring);
++                      bnxt_set_rx_ring_params_p5(bp, ring_type, req,
++                                                 rxr, ring);
+               break;
+       case HWRM_RING_ALLOC_CMPL:
+               req->ring_type = RING_ALLOC_REQ_RING_TYPE_L2_CMPL;
+@@ -7298,7 +7308,7 @@ static int bnxt_hwrm_rx_ring_alloc(struct bnxt *bp,
+       u32 map_idx = bnapi->index;
+       int rc;
+-      rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
++      rc = hwrm_ring_alloc_send_msg(bp, rxr, ring, type, map_idx);
+       if (rc)
+               return rc;
+@@ -7318,7 +7328,7 @@ static int bnxt_hwrm_rx_agg_ring_alloc(struct bnxt *bp,
+       int rc;
+       map_idx = grp_idx + bp->rx_nr_rings;
+-      rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
++      rc = hwrm_ring_alloc_send_msg(bp, rxr, ring, type, map_idx);
+       if (rc)
+               return rc;
+@@ -7342,7 +7352,7 @@ static int bnxt_hwrm_cp_ring_alloc_p5(struct bnxt *bp,
+       ring = &cpr->cp_ring_struct;
+       ring->handle = BNXT_SET_NQ_HDL(cpr);
+-      rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
++      rc = hwrm_ring_alloc_send_msg(bp, NULL, ring, type, map_idx);
+       if (rc)
+               return rc;
+       bnxt_set_db(bp, &cpr->cp_db, type, map_idx, ring->fw_ring_id);
+@@ -7357,7 +7367,7 @@ static int bnxt_hwrm_tx_ring_alloc(struct bnxt *bp,
+       const u32 type = HWRM_RING_ALLOC_TX;
+       int rc;
+-      rc = hwrm_ring_alloc_send_msg(bp, ring, type, tx_idx);
++      rc = hwrm_ring_alloc_send_msg(bp, NULL, ring, type, tx_idx);
+       if (rc)
+               return rc;
+       bnxt_set_db(bp, &txr->tx_db, type, tx_idx, ring->fw_ring_id);
+@@ -7383,7 +7393,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
+               vector = bp->irq_tbl[map_idx].vector;
+               disable_irq_nosync(vector);
+-              rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
++              rc = hwrm_ring_alloc_send_msg(bp, NULL, ring, type, map_idx);
+               if (rc) {
+                       enable_irq(vector);
+                       goto err_out;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index b140799f07d69..9a1be6b71219d 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -1105,6 +1105,7 @@ struct bnxt_rx_ring_info {
+       unsigned long           *rx_agg_bmap;
+       u16                     rx_agg_bmap_size;
++      u32                     rx_page_size;
+       bool                    need_head_pool;
+       dma_addr_t              rx_desc_mapping[MAX_RX_PAGES];
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+index c94a391b1ba5b..85cbeb35681c2 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+@@ -183,7 +183,7 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
+                       u16 cons, u8 *data_ptr, unsigned int len,
+                       struct xdp_buff *xdp)
+ {
+-      u32 buflen = BNXT_RX_PAGE_SIZE;
++      u32 buflen = rxr->rx_page_size;
+       struct bnxt_sw_rx_bd *rx_buf;
+       struct pci_dev *pdev;
+       dma_addr_t mapping;
+@@ -460,7 +460,7 @@ int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+ struct sk_buff *
+ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
+-                 struct page_pool *pool, struct xdp_buff *xdp)
++                 struct bnxt_rx_ring_info *rxr, struct xdp_buff *xdp)
+ {
+       struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
+@@ -468,7 +468,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
+               return NULL;
+       xdp_update_skb_frags_info(skb, num_frags, sinfo->xdp_frags_size,
+-                                BNXT_RX_PAGE_SIZE * num_frags,
++                                rxr->rx_page_size * num_frags,
+                                 xdp_buff_get_skb_flags(xdp));
+       return skb;
+ }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+index 220285e190fcd..8933a0dec09a6 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+@@ -32,6 +32,6 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
+ void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr,
+                             struct xdp_buff *xdp);
+ struct sk_buff *bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb,
+-                                 u8 num_frags, struct page_pool *pool,
++                                 u8 num_frags, struct bnxt_rx_ring_info *rxr,
+                                  struct xdp_buff *xdp);
+ #endif
+-- 
+2.53.0
+
diff --git a/queue-6.18/eth-bnxt-support-qcfg-provided-rx-page-size.patch b/queue-6.18/eth-bnxt-support-qcfg-provided-rx-page-size.patch
new file mode 100644 (file)
index 0000000..c60e1f2
--- /dev/null
@@ -0,0 +1,126 @@
+From a59a81103a6acf1ab7301d46ab0dc041cb976384 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Oct 2025 23:10:32 +0100
+Subject: eth: bnxt: support qcfg provided rx page size
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit f96e1b35779e153be266fd7de50bda0c5553ad21 ]
+
+Implement support for qcfg provided rx page sizes. For that, implement
+the ndo_default_qcfg callback and validate the config on restart. Also,
+use the current config's value in bnxt_init_ring_struct to retain the
+correct size across resets.
+
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Stable-dep-of: d1000fd7995e ("bnxt: fix memory leak in bnxt_queue_mem_alloc error cases")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 36 ++++++++++++++++++++++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h |  1 +
+ 2 files changed, 36 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index fddfdf807950f..52b356f4966ab 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -4323,6 +4323,7 @@ static void bnxt_init_ring_struct(struct bnxt *bp)
+               struct bnxt_rx_ring_info *rxr;
+               struct bnxt_tx_ring_info *txr;
+               struct bnxt_ring_struct *ring;
++              struct netdev_rx_queue *rxq;
+               if (!bnapi)
+                       continue;
+@@ -4340,7 +4341,8 @@ static void bnxt_init_ring_struct(struct bnxt *bp)
+               if (!rxr)
+                       goto skip_rx;
+-              rxr->rx_page_size = BNXT_RX_PAGE_SIZE;
++              rxq = __netif_get_rx_queue(bp->dev, i);
++              rxr->rx_page_size = rxq->qcfg.rx_page_size;
+               ring = &rxr->rx_ring_struct;
+               rmem = &ring->ring_mem;
+@@ -15964,6 +15966,29 @@ static const struct netdev_stat_ops bnxt_stat_ops = {
+       .get_base_stats         = bnxt_get_base_stats,
+ };
++static void bnxt_queue_default_qcfg(struct net_device *dev,
++                                  struct netdev_queue_config *qcfg)
++{
++      qcfg->rx_page_size = BNXT_RX_PAGE_SIZE;
++}
++
++static int bnxt_validate_qcfg(struct bnxt *bp, struct netdev_queue_config *qcfg)
++{
++      /* Older chips need MSS calc so rx_page_size is not supported */
++      if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS) &&
++          qcfg->rx_page_size != BNXT_RX_PAGE_SIZE)
++              return -EINVAL;
++
++      if (!is_power_of_2(qcfg->rx_page_size))
++              return -ERANGE;
++
++      if (qcfg->rx_page_size < BNXT_RX_PAGE_SIZE ||
++          qcfg->rx_page_size > BNXT_MAX_RX_PAGE_SIZE)
++              return -ERANGE;
++
++      return 0;
++}
++
+ static int bnxt_queue_mem_alloc(struct net_device *dev,
+                               struct netdev_queue_config *qcfg,
+                               void *qmem, int idx)
+@@ -15976,6 +16001,10 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
+       if (!bp->rx_ring)
+               return -ENETDOWN;
++      rc = bnxt_validate_qcfg(bp, qcfg);
++      if (rc < 0)
++              return rc;
++
+       rxr = &bp->rx_ring[idx];
+       clone = qmem;
+       memcpy(clone, rxr, sizeof(*rxr));
+@@ -15987,6 +16016,7 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
+       clone->rx_sw_agg_prod = 0;
+       clone->rx_next_cons = 0;
+       clone->need_head_pool = false;
++      clone->rx_page_size = qcfg->rx_page_size;
+       rc = bnxt_alloc_rx_page_pool(bp, clone, rxr->page_pool->p.nid);
+       if (rc)
+@@ -16113,6 +16143,8 @@ static void bnxt_copy_rx_ring(struct bnxt *bp,
+       src_ring = &src->rx_agg_ring_struct;
+       src_rmem = &src_ring->ring_mem;
++      dst->rx_page_size = src->rx_page_size;
++
+       WARN_ON(dst_rmem->nr_pages != src_rmem->nr_pages);
+       WARN_ON(dst_rmem->page_size != src_rmem->page_size);
+       WARN_ON(dst_rmem->flags != src_rmem->flags);
+@@ -16267,6 +16299,8 @@ static const struct netdev_queue_mgmt_ops bnxt_queue_mgmt_ops = {
+       .ndo_queue_mem_free     = bnxt_queue_mem_free,
+       .ndo_queue_start        = bnxt_queue_start,
+       .ndo_queue_stop         = bnxt_queue_stop,
++      .ndo_default_qcfg       = bnxt_queue_default_qcfg,
++      .supported_params       = QCFG_RX_PAGE_SIZE,
+ };
+ static void bnxt_remove_one(struct pci_dev *pdev)
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 9a1be6b71219d..3ca989da0eb02 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -760,6 +760,7 @@ struct nqe_cn {
+ #endif
+ #define BNXT_RX_PAGE_SIZE (1 << BNXT_RX_PAGE_SHIFT)
++#define BNXT_MAX_RX_PAGE_SIZE BIT(15)
+ #define BNXT_MAX_MTU          9500
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-ads7828-fix-external-vref-regulator-handling.patch b/queue-6.18/hwmon-ads7828-fix-external-vref-regulator-handling.patch
new file mode 100644 (file)
index 0000000..c07a4c1
--- /dev/null
@@ -0,0 +1,71 @@
+From 05573f9cac201179c53b2a5fa41a294b66a6f649 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 14:16:45 +0800
+Subject: hwmon: (ads7828) Fix external VREF regulator handling
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit fddb5ceaf901b050ed2a1a7deeecbf97e003435a ]
+
+The driver currently has two issues with the external VREF regulator
+handling in ads7828_probe():
+
+1. All errors from devm_regulator_get_optional() are ignored, causing the
+   driver to incorrectly fall back to internal VREF even for transient
+   errors like -EPROBE_DEFER or genuine failures like -ENOMEM.
+
+2. The external regulator is never enabled. The driver calls
+   regulator_get_voltage() without first calling regulator_enable(),
+   so the VREF pin may remain unpowered if the regulator is not
+   configured as always-on.
+
+Fix both issues by switching to devm_regulator_get_enable_read_voltage(),
+which handles regulator get, enable, and voltage read in one call.
+Only -ENODEV (no regulator specified in device tree) should trigger the
+fallback to internal VREF. All other errors are propagated to the caller.
+
+Fixes: a8ddfea09566 ("hwmon: (ads7828) Accept optional parameters from device tree")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260805061645.1331652-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ads7828.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
+index 436637264056c..20ef4992f5bb8 100644
+--- a/drivers/hwmon/ads7828.c
++++ b/drivers/hwmon/ads7828.c
+@@ -106,12 +106,11 @@ static int ads7828_probe(struct i2c_client *client)
+       struct ads7828_data *data;
+       struct device *hwmon_dev;
+       unsigned int vref_mv = ADS7828_INT_VREF_MV;
+-      unsigned int vref_uv;
++      int vref_uv;
+       bool diff_input = false;
+       bool ext_vref = false;
+       unsigned int regval;
+       enum ads7828_chips chip;
+-      struct regulator *reg;
+       data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
+       if (!data)
+@@ -125,9 +124,11 @@ static int ads7828_probe(struct i2c_client *client)
+       } else if (dev->of_node) {
+               diff_input = of_property_read_bool(dev->of_node,
+                                                  "ti,differential-input");
+-              reg = devm_regulator_get_optional(dev, "vref");
+-              if (!IS_ERR(reg)) {
+-                      vref_uv = regulator_get_voltage(reg);
++              vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref");
++              if (vref_uv < 0) {
++                      if (vref_uv != -ENODEV)
++                              return vref_uv;
++              } else {
+                       vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
+                       if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
+                           vref_mv > ADS7828_EXT_VREF_MV_MAX)
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch b/queue-6.18/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
new file mode 100644 (file)
index 0000000..2a8b01f
--- /dev/null
@@ -0,0 +1,50 @@
+From 8d6687b405b9c2caa6341e1dfc81bf7dc2f47e59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 07:19:20 +0000
+Subject: hwmon: (corsair-psu) fix possible out-of-bounds access on missing
+ string termination
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit 36c4d73ce05d1d8896c2669eb0730d35a02a2ec1 ]
+
+In theory it could be possible that the REPLY_SIZE sized buffers for
+holding the vendor and product strings could be end up missing the null
+termination (for example by malicious hardware built on purpose)
+required by the seq_printf() call. That limits the debugfs printf calls
+to a maximum string length of REPLY_SIZE.
+
+Fixes: d115b51e0e567 ("hwmon: add Corsair PSU HID controller driver")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/anLj9gPWRoRDbQBV@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 4681af6843596..679fb30983465 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -709,7 +709,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->vendor);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
+       return 0;
+ }
+@@ -719,7 +719,7 @@ static int product_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->product);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch b/queue-6.18/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch
new file mode 100644 (file)
index 0000000..f318b7c
--- /dev/null
@@ -0,0 +1,105 @@
+From 26b682eeccf8c3539e863f0ef97e32a5f01b5d10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:42:42 -0700
+Subject: hwmon: (ltc4282) Avoid overflow in maximum power calculation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit edd11a94335747423569500a194c6eaa915f2963 ]
+
+During device initialization in ltc4282_set_max_limits(), the calculation
+of the maximum power limit can suffer from a 32-bit integer overflow.
+
+static int ltc4282_set_max_limits(struct ltc4282_state *st)
+{
+    ...
+    st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI,
+                                      st->rsense) * st->vfs_out;
+    ...
+}
+
+The result of DIV_ROUND_CLOSEST() evaluates to a 32-bit unsigned integer
+on 32-bit architectures. This result is then multiplied by st->vfs_out,
+which is a 16-bit unsigned integer. According to C promotion rules, since
+both operands are 32-bit or smaller, the multiplication is performed in
+32-bit precision.
+
+If the device is configured with a low sense resistor value via the device
+tree (for example, 100 nano-ohms, resulting in st->rsense = 1) and the
+voltage is high, the division result can reach 343,750,000 and st->vfs_out
+can be 33,280. The product of these values is approximately 11.44 trillion,
+which exceeds the maximum capacity of a 32-bit integer and overflows
+before being stored in st->power_max.
+
+This overflow causes a truncated value to be assigned to st->power_max and
+written to the hardware limit register. An incorrect maximum power limit
+can trigger spurious power-bad faults or alarms, which may lead to the
+shutdown of the monitored power rail.
+
+Avoid the problem by calculating and storing the maximum power using 64-bit
+variables.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index 4000bcbc7353d..e5ea1db83da47 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -142,7 +142,7 @@ struct ltc4282_state {
+        */
+       struct ltc4282_cache in0_1_cache[LTC4282_CHAN_VGPIO];
+       u32 vsense_max;
+-      long power_max;
++      s64 power_max;
+       u32 rsense;
+       u16 vdd;
+       u16 vfs_out;
+@@ -623,13 +623,12 @@ static int ltc4282_read(struct device *dev, enum hwmon_sensor_types type,
+ }
+ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
+-                                  long val)
++                                  s64 val)
+ {
+       u32 power;
+       u64 temp;
+-      if (val > st->power_max)
+-              val = st->power_max;
++      val = clamp(val, 0, st->power_max);
+       temp = val * int_pow(U8_MAX, 2) * st->rsense;
+       power = DIV64_U64_ROUND_CLOSEST(temp,
+@@ -639,7 +638,7 @@ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
+ }
+ static int ltc4282_write_power_word(const struct ltc4282_state *st, u32 reg,
+-                                  long val)
++                                  u64 val)
+ {
+       u64 temp = int_pow(U16_MAX, 2) * st->rsense, temp_2;
+       __be16 __raw;
+@@ -1256,7 +1255,8 @@ static int ltc4282_set_max_limits(struct ltc4282_state *st)
+               return ret;
+       /* Power is given by ISENSE * Vout. */
+-      st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI, st->rsense) * st->vfs_out;
++      st->power_max = DIV_ROUND_CLOSEST_ULL((u64)st->vsense_max * DECA * MILLI,
++                                            st->rsense) * st->vfs_out;
+       ret = ltc4282_write_power_byte(st, LTC4282_POWER_MAX, st->power_max);
+       if (ret)
+               return ret;
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-ltc4282-clamp-negative-current-limits.patch b/queue-6.18/hwmon-ltc4282-clamp-negative-current-limits.patch
new file mode 100644 (file)
index 0000000..100ccff
--- /dev/null
@@ -0,0 +1,69 @@
+From 448377d436425cf61b5ddbcc1d7e2823d0ec6f0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 16:26:05 -0700
+Subject: hwmon: (ltc4282) Clamp negative current limits
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit e253dd5f9f6d875a317895bf43ec9534ed7523cb ]
+
+When a negative value is passed to ltc4282_write_curr(), the signed long
+val is cast directly to u64:
+
+drivers/hwmon/ltc4282.c:ltc4282_write_curr() {
+        /* need to pass it in millivolt */
+        u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
+        ...
+}
+
+This cast converts negative inputs into large positive values. The
+subsequent division result overflows the u32 in variable, truncating
+to a pseudo-random positive value. When this is passed to
+ltc4282_write_voltage_byte(), it is clamped to the maximum limit instead
+of zero.
+
+Clamp val to 0 and to the maximum supported upper limit before the cast
+and assign the result to a 64-bit temporary variable before the division
+to avoid the underflow and an also possible overflow.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index e5ea1db83da47..b45a6e128d32e 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -15,6 +15,7 @@
+ #include <linux/hwmon-sysfs.h>
+ #include <linux/i2c.h>
+ #include <linux/math.h>
++#include <linux/math64.h>
+ #include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/mod_devicetable.h>
+@@ -947,8 +948,11 @@ static int ltc4282_curr_reset_hist(struct ltc4282_state *st)
+ static int ltc4282_write_curr(struct ltc4282_state *st, u32 attr,
+                             long val)
+ {
++      s32 ulimit = min_t(u64, INT_MAX,
++                         div_u64((u64)INT_MAX * DECA * MICRO, st->rsense));
++      u64 val64 = clamp(val, 0, ulimit);
+       /* need to pass it in millivolt */
+-      u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
++      u32 in = DIV_ROUND_CLOSEST_ULL(val64 * st->rsense, DECA * MICRO);
+       switch (attr) {
+       case hwmon_curr_max:
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch b/queue-6.18/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch
new file mode 100644 (file)
index 0000000..263112e
--- /dev/null
@@ -0,0 +1,68 @@
+From 2e61ebc39d33c9c30c0e57215677414ba53634ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 17:30:42 -0700
+Subject: hwmon: (ltc4282) Fix parsing adi,current-limit-sense-microvolt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 335698fd7f60b6707b21fda725f97f35fa956b07 ]
+
+ltc4282_parse_dt() evaluates the wrong variable when parsing the current
+limit.
+
+When the adi,current-limit-sense-microvolt property is parsed into
+st->vsense_max, the subsequent switch statement evaluates the unrelated
+val variable instead of st->vsense_max:
+
+drivers/hwmon/ltc4282.c:ltc4282_parse_dt() {
+    ...
+        ret = device_property_read_u32(dev, "adi,current-limit-sense-microvolt",
+                                       &st->vsense_max);
+        if (!ret) {
+                int reg_val;
+
+                switch (val) {
+                case 12500:
+                        reg_val = 0;
+                        break;
+    ...
+}
+
+Because val holds a small integer representing vin_mode (from 0 to 3), it
+never matches any of the valid current limit cases.
+
+This causes it to always fall through to the default error case, return
+-EINVAL, and aborts probe initialization for any device tree using this
+property.
+
+Validate st->vsense_max instead to fix the problem.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index b45a6e128d32e..269f96738f5b3 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -1427,7 +1427,7 @@ static int ltc4282_setup(struct ltc4282_state *st, struct device *dev)
+       if (!ret) {
+               int reg_val;
+-              switch (val) {
++              switch (st->vsense_max) {
+               case 12500:
+                       reg_val = 0;
+                       break;
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch b/queue-6.18/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
new file mode 100644 (file)
index 0000000..f83800e
--- /dev/null
@@ -0,0 +1,57 @@
+From 44b774092b414caeb155a01a7502fcf314c31595 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:48:42 +0800
+Subject: hwmon: (nzxt-smart2) Check return value of init_device() in probe
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit d533882ce1060866a590257f2c77ee23eabef5b8 ]
+
+The init_device() call in nzxt_smart2_hid_probe() can fail because it
+sends HID output reports to the hardware to detect fans and set the
+update interval.  If the hardware is not responding or the HID reports
+fail, init_device() returns a negative error code.
+
+However, the return value was ignored, causing the probe to continue
+and register an hwmon device even though the device was never properly
+initialized.  This leads to an inconsistent state where the driver
+reports stale data or blocks on wait queues that will never be woken.
+
+The same function's return value is already checked in the
+reset_resume() handler, confirming the author's intent that errors
+should be propagated.
+
+Note that this fix was not possible before commit 59d104b54b0b
+("hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop")
+because the out_hw_close error path was missing hid_device_io_stop(),
+which would have opened a use-after-free risk window.
+
+Fixes: 53e68c20aeb1 ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2.")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260804074842.505923-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/nzxt-smart2.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
+index ff0c0bee0e839..efc78a8f58c88 100644
+--- a/drivers/hwmon/nzxt-smart2.c
++++ b/drivers/hwmon/nzxt-smart2.c
+@@ -754,7 +754,11 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
+       hid_device_io_start(hdev);
+-      init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      ret = init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      if (ret) {
++              dev_err(&hdev->dev, "init_device failed: %d\n", ret);
++              goto out_hw_close;
++      }
+       drvdata->hwmon =
+               hwmon_device_register_with_info(&hdev->dev, "nzxtsmart2", drvdata,
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-pmbus-fix-type-confusion-in-notification-logic.patch b/queue-6.18/hwmon-pmbus-fix-type-confusion-in-notification-logic.patch
new file mode 100644 (file)
index 0000000..8ce4bde
--- /dev/null
@@ -0,0 +1,234 @@
+From be4c8782c47bbeb107212621f1f7ec2ea28590a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:57:35 -0700
+Subject: hwmon: (pmbus) Fix type confusion in notification logic
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 59bd68ab05a8f9c9a60b6ec44682084184803ff4 ]
+
+Sashiko reports:
+
+At the start of the loop in pmbus_notify(), the code unconditionally casts
+every attribute to a struct sensor_device_attribute:
+
+drivers/hwmon/pmbus/pmbus_core.c:pmbus_notify() {
+    for (i = 0; i < data->num_attributes; i++) {
+        struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
+        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+        int index = attr->index;
+...
+}
+
+However, data->group.attrs can contain other types like struct
+pmbus_samples_reg or struct pmbus_sensor, which only embed a base
+struct device_attribute.
+
+If da is a struct pmbus_samples_reg, dev_attr is the last member. Casting
+it to struct sensor_device_attribute and reading the index field appears
+to access memory past the end of the allocation, which might trigger a
+slab-out-of-bounds read.
+
+Additionally, if da is a struct pmbus_sensor, casting it causes the index
+field to overlap with the page, phase, and reg fields. Could this produce
+a garbage mask on little-endian systems that spuriously matches the target
+reg, page, and flags during an alert?
+
+Fix the problem by using struct sensor_device_attr in struct pmbus_sensor
+and struct pmbus_label. Since those attributes never trigger a
+notification, set the value of attr->index to -1 for them. Use this value
+to distinguish from boolean attributes which _can_ trigger a notification
+and use the index field to encode mask, page, and register values.
+
+Fixes: f469bde9afd1 ("hwmon: (pmbus/core) Notify hwmon events")
+Cc: Vincent Jardin <vjardin@free.fr>
+Tested-by: Vincent Jardin <vjardin@free.fr>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 61 +++++++++++++++++++-------------
+ 1 file changed, 37 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index a95ffd563018d..20a26db668940 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -46,7 +46,7 @@ module_param(wp, int, 0444);
+ struct pmbus_sensor {
+       struct pmbus_sensor *next;
+       char name[PMBUS_NAME_SIZE];     /* sysfs sensor name */
+-      struct device_attribute attribute;
++      struct sensor_device_attribute attribute;
+       u8 page;                /* page number */
+       u8 phase;               /* phase number, 0xff for all phases */
+       u16 reg;                /* register */
+@@ -69,7 +69,7 @@ struct pmbus_boolean {
+ struct pmbus_label {
+       char name[PMBUS_NAME_SIZE];     /* sysfs label name */
+-      struct device_attribute attribute;
++      struct sensor_device_attribute attribute;
+       char label[PMBUS_NAME_SIZE];    /* label */
+ };
+ #define to_pmbus_label(_attr) \
+@@ -1218,7 +1218,8 @@ static ssize_t pmbus_show_sensor(struct device *dev,
+                                struct device_attribute *devattr, char *buf)
+ {
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_sensor *sensor = to_pmbus_sensor(attr);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       s64 val;
+@@ -1238,7 +1239,8 @@ static ssize_t pmbus_set_sensor(struct device *dev,
+ {
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+-      struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_sensor *sensor = to_pmbus_sensor(attr);
+       s64 val;
+       int ret;
+       u16 regval;
+@@ -1260,7 +1262,8 @@ static ssize_t pmbus_set_sensor(struct device *dev,
+ static ssize_t pmbus_show_label(struct device *dev,
+                               struct device_attribute *da, char *buf)
+ {
+-      struct pmbus_label *label = to_pmbus_label(da);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++      struct pmbus_label *label = to_pmbus_label(attr);
+       return sysfs_emit(buf, "%s\n", label->label);
+ }
+@@ -1413,8 +1416,8 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+                                            bool update, bool readonly,
+                                            bool writeonly, bool convert)
+ {
++      struct sensor_device_attribute *a;
+       struct pmbus_sensor *sensor;
+-      struct device_attribute *a;
+       sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
+       if (!sensor)
+@@ -1438,12 +1441,11 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+       sensor->update = update;
+       sensor->convert = convert;
+       sensor->data = -ENODATA;
+-      pmbus_dev_attr_init(a, sensor->name,
+-                          readonly ? 0444 : 0644,
+-                          writeonly ? pmbus_show_zero : pmbus_show_sensor,
+-                          pmbus_set_sensor);
++      pmbus_attr_init(a, sensor->name, readonly ? 0444 : 0644,
++                      writeonly ? pmbus_show_zero : pmbus_show_sensor,
++                      pmbus_set_sensor, -1);
+-      if (pmbus_add_attribute(data, &a->attr))
++      if (pmbus_add_attribute(data, &a->dev_attr.attr))
+               return NULL;
+       sensor->next = data->sensors;
+@@ -1460,8 +1462,8 @@ static int pmbus_add_label(struct pmbus_data *data,
+                          const char *name, int seq,
+                          const char *lstring, int index, int phase)
+ {
++      struct sensor_device_attribute *a;
+       struct pmbus_label *label;
+-      struct device_attribute *a;
+       label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL);
+       if (!label)
+@@ -1485,8 +1487,8 @@ static int pmbus_add_label(struct pmbus_data *data,
+                                lstring, index, phase);
+       }
+-      pmbus_dev_attr_init(a, label->name, 0444, pmbus_show_label, NULL);
+-      return pmbus_add_attribute(data, &a->attr);
++      pmbus_attr_init(a, label->name, 0444, pmbus_show_label, NULL, -1);
++      return pmbus_add_attribute(data, &a->dev_attr.attr);
+ }
+ /*
+@@ -2374,7 +2376,7 @@ struct pmbus_samples_attr {
+ struct pmbus_samples_reg {
+       int page;
+       struct pmbus_samples_attr *attr;
+-      struct device_attribute dev_attr;
++      struct sensor_device_attribute attribute;
+ };
+ static struct pmbus_samples_attr pmbus_samples_registers[] = {
+@@ -2396,14 +2398,15 @@ static struct pmbus_samples_attr pmbus_samples_registers[] = {
+       }
+ };
+-#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, dev_attr)
++#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, attribute)
+ static ssize_t pmbus_show_samples(struct device *dev,
+                                 struct device_attribute *devattr, char *buf)
+ {
+       int val;
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_samples_reg *reg = to_samples_reg(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_samples_reg *reg = to_samples_reg(attr);
+       scoped_guard(pmbus_lock, client) {
+               val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
+@@ -2421,7 +2424,8 @@ static ssize_t pmbus_set_samples(struct device *dev,
+       int ret;
+       long val;
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_samples_reg *reg = to_samples_reg(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_samples_reg *reg = to_samples_reg(attr);
+       if (kstrtol(buf, 0, &val) < 0)
+               return -EINVAL;
+@@ -2436,6 +2440,7 @@ static ssize_t pmbus_set_samples(struct device *dev,
+ static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
+                                 struct pmbus_samples_attr *attr)
+ {
++      struct sensor_device_attribute *a;
+       struct pmbus_samples_reg *reg;
+       reg = devm_kzalloc(data->dev, sizeof(*reg), GFP_KERNEL);
+@@ -2445,10 +2450,12 @@ static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
+       reg->attr = attr;
+       reg->page = page;
+-      pmbus_dev_attr_init(&reg->dev_attr, attr->name, 0644,
+-                          pmbus_show_samples, pmbus_set_samples);
++      a = &reg->attribute;
++
++      pmbus_attr_init(a, attr->name, 0644,
++                      pmbus_show_samples, pmbus_set_samples, -1);
+-      return pmbus_add_attribute(data, &reg->dev_attr.attr);
++      return pmbus_add_attribute(data, &a->dev_attr.attr);
+ }
+ static int pmbus_add_samples_attributes(struct i2c_client *client,
+@@ -2956,9 +2963,15 @@ static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
+               struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
+               struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+               int index = attr->index;
+-              u16 smask = pb_index_to_mask(index);
+-              u8 spage = pb_index_to_page(index);
+-              u16 sreg = pb_index_to_reg(index);
++              u16 smask, sreg;
++              u8 spage;
++
++              if (index == -1)
++                      continue;
++
++              smask = pb_index_to_mask(index);
++              spage = pb_index_to_page(index);
++              sreg = pb_index_to_reg(index);
+               if (reg == sreg && page == spage && (smask & flags)) {
+                       dev_dbg(data->dev, "sysfs notify: %s", da->attr.name);
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch b/queue-6.18/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
new file mode 100644 (file)
index 0000000..11f0a3e
--- /dev/null
@@ -0,0 +1,71 @@
+From 21c8dbd4d0f82468f8825dd772f74951d344f1d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 14:12:31 -0700
+Subject: hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 0dabe8a56f772f0ece46d2597799f412c277d874 ]
+
+In lm25066_probe(), the PMBus coefficients for current and power are
+scaled based on the shunt resistor value. The calculation evaluates the
+multiplication using 32-bit arithmetic because info->m is an int and
+shunt is a u32:
+
+static int lm25066_probe(struct i2c_client *client) {
+    ...
+    info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+    info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
+    ...
+}
+
+For large coefficients like 26882 (LM25056) or 15076 (LM5066i), a device
+tree shunt-resistor-micro-ohms value exceeding approximately 159,000
+(159 mOhm, which is physically valid for low-current applications) causes
+the intermediate product to exceed UINT_MAX (4,294,967,295). This results
+in a silent wraparound before the division by 1000.
+
+Furthermore, if the wrapped value has the most significant bit set,
+converting it back to the signed int info->m results in negative
+coefficients. This logic error leads to drastically corrupted current and
+power readings, which can cause erratic thermal or power management
+behavior in the system.
+
+Fix the problem by using 64-bit operations for the multiply/divide
+operations. This can still overflow, but only for unreasonably large
+shunt resistor values.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: 94ee5fcc240fe ("hwmon: (pmbus/lm25066) Support configurable sense resistor values")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index dd7275a67a0ab..7774d678022e2 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
++#include <linux/math.h>
+ #include <linux/of.h>
+ #include "pmbus.h"
+@@ -540,8 +541,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
+               shunt = 1000;
+-      info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+-      info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
++      info->m[PSC_CURRENT_IN] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_CURRENT_IN] * shunt, 1000);
++      info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_POWER] * shunt, 1000);
+ #if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)
+       /* LM25056 doesn't support OPERATION */
+-- 
+2.53.0
+
diff --git a/queue-6.18/hwmon-pmbus_core-use-guard-for-mutex-protection.patch b/queue-6.18/hwmon-pmbus_core-use-guard-for-mutex-protection.patch
new file mode 100644 (file)
index 0000000..0857207
--- /dev/null
@@ -0,0 +1,558 @@
+From 6aee13770ebae0710e220f91c03381d5dd5f0dbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 07:45:55 -0700
+Subject: hwmon: (pmbus_core) Use guard() for mutex protection
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit bd1c178affd7d1ca86eaf97cf797e0d15e57eb0a ]
+
+Simplify the code by using guard() and scoped_guard() instead of
+mutex_lock()/mutex_unlock() sequences.
+
+This patch changes semantics for debugfs accesses. Previously, those
+used mutex_lock_interruptible() and not mutex_lock(). This change is
+intentional and should have little if any impact since locks should not
+be held for a significant amount of time and debugfs accesses are less
+critical than sysfs accesses (which never used interruptable locks).
+
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Stable-dep-of: 59bd68ab05a8 ("hwmon: (pmbus) Fix type confusion in notification logic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 277 ++++++++++++-------------------
+ 1 file changed, 107 insertions(+), 170 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index c9e3ec4552efd..a95ffd563018d 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1156,12 +1156,11 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
+       int ret, status;
+       u16 regval;
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
++
+       status = pmbus_get_status(client, page, reg);
+-      if (status < 0) {
+-              ret = status;
+-              goto unlock;
+-      }
++      if (status < 0)
++              return status;
+       if (s1)
+               pmbus_update_sensor_data(client, s1);
+@@ -1173,7 +1172,7 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
+               if (data->revision >= PMBUS_REV_12) {
+                       ret = _pmbus_write_byte_data(client, page, reg, regval);
+                       if (ret)
+-                              goto unlock;
++                              return ret;
+               } else {
+                       pmbus_clear_fault_page(client, page);
+               }
+@@ -1181,14 +1180,10 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
+       if (s1 && s2) {
+               s64 v1, v2;
+-              if (s1->data < 0) {
+-                      ret = s1->data;
+-                      goto unlock;
+-              }
+-              if (s2->data < 0) {
+-                      ret = s2->data;
+-                      goto unlock;
+-              }
++              if (s1->data < 0)
++                      return s1->data;
++              if (s2->data < 0)
++                      return s2->data;
+               v1 = pmbus_reg2data(data, s1);
+               v2 = pmbus_reg2data(data, s2);
+@@ -1196,8 +1191,6 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
+       } else {
+               ret = !!regval;
+       }
+-unlock:
+-      mutex_unlock(&data->update_lock);
+       return ret;
+ }
+@@ -1227,16 +1220,16 @@ static ssize_t pmbus_show_sensor(struct device *dev,
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+-      ssize_t ret;
++      s64 val;
+-      mutex_lock(&data->update_lock);
+-      pmbus_update_sensor_data(client, sensor);
+-      if (sensor->data < 0)
+-              ret = sensor->data;
+-      else
+-              ret = sysfs_emit(buf, "%lld\n", pmbus_reg2data(data, sensor));
+-      mutex_unlock(&data->update_lock);
+-      return ret;
++      scoped_guard(pmbus_lock, client) {
++              pmbus_update_sensor_data(client, sensor);
++              if (sensor->data < 0)
++                      return sensor->data;
++              val = pmbus_reg2data(data, sensor);
++      }
++
++      return sysfs_emit(buf, "%lld\n", val);
+ }
+ static ssize_t pmbus_set_sensor(struct device *dev,
+@@ -1246,7 +1239,6 @@ static ssize_t pmbus_set_sensor(struct device *dev,
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
+-      ssize_t rv = count;
+       s64 val;
+       int ret;
+       u16 regval;
+@@ -1254,15 +1246,15 @@ static ssize_t pmbus_set_sensor(struct device *dev,
+       if (kstrtos64(buf, 10, &val) < 0)
+               return -EINVAL;
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
++
+       regval = pmbus_data2reg(data, sensor, val);
+       ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
+       if (ret < 0)
+-              rv = ret;
+-      else
+-              sensor->data = -ENODATA;
+-      mutex_unlock(&data->update_lock);
+-      return rv;
++              return ret;
++
++      sensor->data = -ENODATA;
++      return count;
+ }
+ static ssize_t pmbus_show_label(struct device *dev,
+@@ -1364,7 +1356,7 @@ static int pmbus_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+       struct pmbus_data *pmbus_data = tdata->pmbus_data;
+       struct i2c_client *client = to_i2c_client(pmbus_data->dev);
+       struct device *dev = pmbus_data->hwmon_dev;
+-      int ret = 0;
++      int _temp;
+       if (!dev) {
+               /* May not even get to hwmon yet */
+@@ -1372,15 +1364,15 @@ static int pmbus_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+               return 0;
+       }
+-      mutex_lock(&pmbus_data->update_lock);
+-      pmbus_update_sensor_data(client, sensor);
+-      if (sensor->data < 0)
+-              ret = sensor->data;
+-      else
+-              *temp = (int)pmbus_reg2data(pmbus_data, sensor);
+-      mutex_unlock(&pmbus_data->update_lock);
++      scoped_guard(pmbus_lock, client) {
++              pmbus_update_sensor_data(client, sensor);
++              if (sensor->data < 0)
++                      return sensor->data;
++              _temp = (int)pmbus_reg2data(pmbus_data, sensor);
++      }
+-      return ret;
++      *temp = _temp;
++      return 0;
+ }
+ static const struct thermal_zone_device_ops pmbus_thermal_ops = {
+@@ -2412,13 +2404,12 @@ static ssize_t pmbus_show_samples(struct device *dev,
+       int val;
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_samples_reg *reg = to_samples_reg(devattr);
+-      struct pmbus_data *data = i2c_get_clientdata(client);
+-      mutex_lock(&data->update_lock);
+-      val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
+-      mutex_unlock(&data->update_lock);
+-      if (val < 0)
+-              return val;
++      scoped_guard(pmbus_lock, client) {
++              val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
++              if (val < 0)
++                      return val;
++      }
+       return sysfs_emit(buf, "%d\n", val);
+ }
+@@ -2431,14 +2422,13 @@ static ssize_t pmbus_set_samples(struct device *dev,
+       long val;
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_samples_reg *reg = to_samples_reg(devattr);
+-      struct pmbus_data *data = i2c_get_clientdata(client);
+       if (kstrtol(buf, 0, &val) < 0)
+               return -EINVAL;
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
++
+       ret = _pmbus_write_word_data(client, reg->page, reg->attr->reg, val);
+-      mutex_unlock(&data->update_lock);
+       return ret ? : count;
+ }
+@@ -2950,14 +2940,9 @@ static int _pmbus_is_enabled(struct i2c_client *client, u8 page)
+ static int __maybe_unused pmbus_is_enabled(struct i2c_client *client, u8 page)
+ {
+-      struct pmbus_data *data = i2c_get_clientdata(client);
+-      int ret;
++      guard(pmbus_lock)(client);
+-      mutex_lock(&data->update_lock);
+-      ret = _pmbus_is_enabled(client, page);
+-      mutex_unlock(&data->update_lock);
+-
+-      return ret;
++      return _pmbus_is_enabled(client, page);
+ }
+ #define to_dev_attr(_dev_attr) \
+@@ -2988,14 +2973,13 @@ static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
+       }
+ }
+-static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flags,
++static int _pmbus_get_flags(struct i2c_client *client, u8 page, unsigned int *flags,
+                           unsigned int *event, bool notify)
+ {
++      struct pmbus_data *data = i2c_get_clientdata(client);
+       int i, status;
+       const struct pmbus_status_category *cat;
+       const struct pmbus_status_assoc *bit;
+-      struct device *dev = data->dev;
+-      struct i2c_client *client = to_i2c_client(dev);
+       int func = data->info->func[page];
+       *flags = 0;
+@@ -3071,16 +3055,12 @@ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flag
+       return 0;
+ }
+-static int __maybe_unused pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flags,
++static int __maybe_unused pmbus_get_flags(struct i2c_client *client, u8 page, unsigned int *flags,
+                                         unsigned int *event, bool notify)
+ {
+-      int ret;
+-
+-      mutex_lock(&data->update_lock);
+-      ret = _pmbus_get_flags(data, page, flags, event, notify);
+-      mutex_unlock(&data->update_lock);
++      guard(pmbus_lock)(client);
+-      return ret;
++      return _pmbus_get_flags(client, page, flags, event, notify);
+ }
+ #if IS_ENABLED(CONFIG_REGULATOR)
+@@ -3096,17 +3076,13 @@ static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
+ {
+       struct device *dev = rdev_get_dev(rdev);
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_data *data = i2c_get_clientdata(client);
+       u8 page = rdev_get_id(rdev);
+-      int ret;
+-      mutex_lock(&data->update_lock);
+-      ret = pmbus_update_byte_data(client, page, PMBUS_OPERATION,
+-                                   PB_OPERATION_CONTROL_ON,
+-                                   enable ? PB_OPERATION_CONTROL_ON : 0);
+-      mutex_unlock(&data->update_lock);
++      guard(pmbus_lock)(client);
+-      return ret;
++      return pmbus_update_byte_data(client, page, PMBUS_OPERATION,
++                                    PB_OPERATION_CONTROL_ON,
++                                    enable ? PB_OPERATION_CONTROL_ON : 0);
+ }
+ static int pmbus_regulator_enable(struct regulator_dev *rdev)
+@@ -3123,54 +3099,41 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
+ {
+       struct device *dev = rdev_get_dev(rdev);
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_data *data = i2c_get_clientdata(client);
+       int event;
+-      return pmbus_get_flags(data, rdev_get_id(rdev), flags, &event, false);
++      return pmbus_get_flags(client, rdev_get_id(rdev), flags, &event, false);
+ }
+ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
+ {
+       struct device *dev = rdev_get_dev(rdev);
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_data *data = i2c_get_clientdata(client);
+       u8 page = rdev_get_id(rdev);
+       int status, ret;
+       int event;
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
++
+       status = pmbus_get_status(client, page, PMBUS_STATUS_WORD);
+-      if (status < 0) {
+-              ret = status;
+-              goto unlock;
+-      }
++      if (status < 0)
++              return status;
+-      if (status & PB_STATUS_OFF) {
+-              ret = REGULATOR_STATUS_OFF;
+-              goto unlock;
+-      }
++      if (status & PB_STATUS_OFF)
++              return REGULATOR_STATUS_OFF;
+       /* If regulator is ON & reports power good then return ON */
+-      if (!(status & PB_STATUS_POWER_GOOD_N)) {
+-              ret = REGULATOR_STATUS_ON;
+-              goto unlock;
+-      }
++      if (!(status & PB_STATUS_POWER_GOOD_N))
++              return REGULATOR_STATUS_ON;
+-      ret = _pmbus_get_flags(data, rdev_get_id(rdev), &status, &event, false);
++      ret = _pmbus_get_flags(client, rdev_get_id(rdev), &status, &event, false);
+       if (ret)
+-              goto unlock;
++              return ret;
+       if (status & (REGULATOR_ERROR_UNDER_VOLTAGE | REGULATOR_ERROR_OVER_CURRENT |
+-         REGULATOR_ERROR_REGULATION_OUT | REGULATOR_ERROR_FAIL | REGULATOR_ERROR_OVER_TEMP)) {
+-              ret = REGULATOR_STATUS_ERROR;
+-              goto unlock;
+-      }
+-
+-      ret = REGULATOR_STATUS_UNDEFINED;
++         REGULATOR_ERROR_REGULATION_OUT | REGULATOR_ERROR_FAIL | REGULATOR_ERROR_OVER_TEMP))
++              return REGULATOR_STATUS_ERROR;
+-unlock:
+-      mutex_unlock(&data->update_lock);
+-      return ret;
++      return REGULATOR_STATUS_UNDEFINED;
+ }
+ static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
+@@ -3235,19 +3198,16 @@ static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
+               .class = PSC_VOLTAGE_OUT,
+               .convert = true,
+       };
+-      int ret;
++      int voltage;
+-      mutex_lock(&data->update_lock);
+-      s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT);
+-      if (s.data < 0) {
+-              ret = s.data;
+-              goto unlock;
++      scoped_guard(pmbus_lock, client) {
++              s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT);
++              if (s.data < 0)
++                      return s.data;
++              voltage = (int)pmbus_reg2data(data, &s);
+       }
+-      ret = (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */
+-unlock:
+-      mutex_unlock(&data->update_lock);
+-      return ret;
++      return voltage * 1000; /* unit is uV */
+ }
+ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+@@ -3264,22 +3224,18 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+       };
+       int val = DIV_ROUND_CLOSEST(min_uv, 1000); /* convert to mV */
+       int low, high;
+-      int ret;
+       *selector = 0;
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
++
+       low = pmbus_regulator_get_low_margin(client, s.page);
+-      if (low < 0) {
+-              ret = low;
+-              goto unlock;
+-      }
++      if (low < 0)
++              return low;
+       high = pmbus_regulator_get_high_margin(client, s.page);
+-      if (high < 0) {
+-              ret = high;
+-              goto unlock;
+-      }
++      if (high < 0)
++              return high;
+       /* Make sure we are within margins */
+       if (low > val)
+@@ -3289,10 +3245,7 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+       val = pmbus_data2reg(data, &s, val);
+-      ret = _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val);
+-unlock:
+-      mutex_unlock(&data->update_lock);
+-      return ret;
++      return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val);
+ }
+ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+@@ -3302,7 +3255,6 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       int val, low, high;
+-      int ret;
+       if (data->flags & PMBUS_VOUT_PROTECTED)
+               return 0;
+@@ -3315,29 +3267,20 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+       val = DIV_ROUND_CLOSEST(rdev->desc->min_uV +
+                               (rdev->desc->uV_step * selector), 1000); /* convert to mV */
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
+       low = pmbus_regulator_get_low_margin(client, rdev_get_id(rdev));
+-      if (low < 0) {
+-              ret = low;
+-              goto unlock;
+-      }
++      if (low < 0)
++              return low;
+       high = pmbus_regulator_get_high_margin(client, rdev_get_id(rdev));
+-      if (high < 0) {
+-              ret = high;
+-              goto unlock;
+-      }
++      if (high < 0)
++              return high;
+-      if (val >= low && val <= high) {
+-              ret = val * 1000; /* unit is uV */
+-              goto unlock;
+-      }
++      if (val >= low && val <= high)
++              return val * 1000; /* unit is uV */
+-      ret = 0;
+-unlock:
+-      mutex_unlock(&data->update_lock);
+-      return ret;
++      return 0;
+ }
+ const struct regulator_ops pmbus_regulator_ops = {
+@@ -3478,16 +3421,16 @@ static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
+       struct i2c_client *client = to_i2c_client(data->dev);
+       int i, status, event;
+-      mutex_lock(&data->update_lock);
++      guard(pmbus_lock)(client);
++
+       for (i = 0; i < data->info->pages; i++) {
+-              _pmbus_get_flags(data, i, &status, &event, true);
++              _pmbus_get_flags(client, i, &status, &event, true);
+               if (event)
+                       pmbus_regulator_notify(data, i, event);
+       }
+       pmbus_clear_faults(client);
+-      mutex_unlock(&data->update_lock);
+       return IRQ_HANDLED;
+ }
+@@ -3543,15 +3486,13 @@ static struct dentry *pmbus_debugfs_dir;       /* pmbus debugfs directory */
+ static int pmbus_debugfs_get(void *data, u64 *val)
+ {
+-      int rc;
+       struct pmbus_debugfs_entry *entry = data;
+-      struct pmbus_data *pdata = i2c_get_clientdata(entry->client);
++      struct i2c_client *client = entry->client;
++      int rc;
+-      rc = mutex_lock_interruptible(&pdata->update_lock);
+-      if (rc)
+-              return rc;
+-      rc = _pmbus_read_byte_data(entry->client, entry->page, entry->reg);
+-      mutex_unlock(&pdata->update_lock);
++      guard(pmbus_lock)(client);
++
++      rc = _pmbus_read_byte_data(client, entry->page, entry->reg);
+       if (rc < 0)
+               return rc;
+@@ -3564,15 +3505,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(pmbus_debugfs_ops, pmbus_debugfs_get, NULL,
+ static int pmbus_debugfs_get_status(void *data, u64 *val)
+ {
+-      int rc;
+       struct pmbus_debugfs_entry *entry = data;
+-      struct pmbus_data *pdata = i2c_get_clientdata(entry->client);
++      struct i2c_client *client = entry->client;
++      struct pmbus_data *pdata = i2c_get_clientdata(client);
++      int rc;
+-      rc = mutex_lock_interruptible(&pdata->update_lock);
+-      if (rc)
+-              return rc;
+-      rc = pdata->read_status(entry->client, entry->page);
+-      mutex_unlock(&pdata->update_lock);
++      guard(pmbus_lock)(client);
++
++      rc = pdata->read_status(client, entry->page);
+       if (rc < 0)
+               return rc;
+@@ -3588,17 +3528,14 @@ static ssize_t pmbus_debugfs_block_read(struct file *file, char __user *buf,
+ {
+       int rc;
+       struct pmbus_debugfs_entry *entry = file->private_data;
+-      struct pmbus_data *pdata = i2c_get_clientdata(entry->client);
++      struct i2c_client *client = entry->client;
+       char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
+-      rc = mutex_lock_interruptible(&pdata->update_lock);
+-      if (rc)
+-              return rc;
+-      rc = pmbus_read_block_data(entry->client, entry->page, entry->reg,
+-                                 data);
+-      mutex_unlock(&pdata->update_lock);
+-      if (rc < 0)
+-              return rc;
++      scoped_guard(pmbus_lock, client) {
++              rc = pmbus_read_block_data(client, entry->page, entry->reg, data);
++              if (rc < 0)
++                      return rc;
++      }
+       /* Add newline at the end of a read data */
+       data[rc] = '\n';
+-- 
+2.53.0
+
diff --git a/queue-6.18/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch b/queue-6.18/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
new file mode 100644 (file)
index 0000000..d9da3f8
--- /dev/null
@@ -0,0 +1,259 @@
+From 6b5a62c1854f99c5c70617574cde5b6944d75c6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:05 +0300
+Subject: ipvs: avoid out-of-bounds write in ip_vs_nat_icmp
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 646922a0379496154e8c8faca4f8e2fd9100cacc ]
+
+Sashiko warns that local attacker can modify the packet
+while it is processed by IPVS. Some places read the
+IP ihl field multiple times which can cause out-of-bounds
+access. One such place is ip_vs_nat_icmp where we
+can write after the validated area.
+
+Fix it by providing ciph argument just like it is done for
+IPv6 and use ciph->len as offset to the embedded transport
+header.
+
+Modify some IPv4 header checks by reading the ihl field
+only once.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://sashiko.dev/#/patchset/20260722101517.36313-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h             |  2 +-
+ net/netfilter/ipvs/ip_vs_core.c | 67 +++++++++++++++++----------------
+ net/netfilter/ipvs/ip_vs_xmit.c |  2 +-
+ 3 files changed, 36 insertions(+), 35 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 17a97086b294f..cbad9c74a8868 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1720,7 +1720,7 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int dir, unsigned int toff,
+-                  bool has_ports);
++                  bool has_ports, struct ip_vs_iphdr *ciph);
+ #ifdef CONFIG_IP_VS_IPV6
+ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index 6207a91e93f3b..586346110cd89 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -747,28 +747,27 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
+  */
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int inout, unsigned int toff,
+-                  bool has_ports)
++                  bool has_ports, struct ip_vs_iphdr *ciph)
+ {
+       struct iphdr *iph        = ip_hdr(skb);
+       struct icmphdr *icmph    = (struct icmphdr *)(skb->data + toff);
+-      struct iphdr *ciph       = (struct iphdr *)(icmph + 1);
+-      unsigned int coff __maybe_unused = toff + sizeof(struct icmphdr);
++      struct iphdr *cih        = (struct iphdr *)(icmph + 1);
+       if (inout) {
+               iph->saddr = cp->vaddr.ip;
+               ip_send_check(iph);
+-              ciph->daddr = cp->vaddr.ip;
+-              ip_send_check(ciph);
++              cih->daddr = cp->vaddr.ip;
++              ip_send_check(cih);
+       } else {
+               iph->daddr = cp->daddr.ip;
+               ip_send_check(iph);
+-              ciph->saddr = cp->daddr.ip;
+-              ip_send_check(ciph);
++              cih->saddr = cp->daddr.ip;
++              ip_send_check(cih);
+       }
+       /* the TCP/UDP/SCTP port */
+       if (has_ports) {
+-              __be16 *ports = (void *)ciph + ciph->ihl*4;
++              __be16 *ports = (void *)(skb->data + ciph->len);
+               if (inout)
+                       ports[1] = cp->vport;
+@@ -782,10 +781,10 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       if (inout)
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered outgoing ICMP");
+       else
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered incoming ICMP");
+ }
+@@ -878,7 +877,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
+               ip_vs_nat_icmp_v6(skb, pp, cp, 1, toff, has_ports, ciph);
+       else
+ #endif
+-              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports);
++              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports, ciph);
+       if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
+               goto out;
+@@ -914,7 +913,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       struct ip_vs_iphdr ciph;
+       struct ip_vs_conn *cp;
+       struct ip_vs_protocol *pp;
+-      unsigned int offset, ihl;
++      unsigned int offset;
+       union nf_inet_addr snet;
+       *related = 1;
+@@ -927,7 +926,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+                       return NF_ACCEPT;
+       }
+-      ihl = ipvsh->len;
+       offset = ipvsh->len;
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
+@@ -953,11 +951,15 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      pp = ip_vs_proto_get(cih->protocol);
++      pp = ip_vs_proto_get(ciph.protocol);
+       if (!pp)
+               return NF_ACCEPT;
+@@ -968,8 +970,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking outgoing ICMP for");
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order */
+       cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
+                            ipvs, AF_INET, skb, &ciph);
+@@ -977,8 +977,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+               return NF_ACCEPT;
+       snet.ip = ipvsh->saddr.ip;
+-      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph, ihl,
+-                                  hooknum);
++      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph,
++                                  ipvsh->len, hooknum);
+ }
+ #ifdef CONFIG_IP_VS_IPV6
+@@ -1625,10 +1625,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!cih)
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      raddr = (union nf_inet_addr *)&cih->daddr;
+       hlen_ipip = cih->ihl * 4;
++      if (!(cih->version == 4 && hlen_ipip >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++      raddr = (union nf_inet_addr *)&cih->daddr;
+       /* Special case for errors for IPIP/UDP/GRE tunnel packets */
+       tunnel = false;
+@@ -1645,9 +1647,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+               if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP)
+                       return NF_ACCEPT;
+               offset += hlen_ipip;
+-              cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-              if (!(cih && cih->version == 4 && cih->ihl >= 5))
+-                      return NF_ACCEPT; /* The packet looks wrong, ignore */
+               tunnel = true;
+       } else if ((cih->protocol == IPPROTO_UDP ||     /* Can be UDP encap */
+                   cih->protocol == IPPROTO_GRE) &&    /* Can be GRE encap */
+@@ -1672,21 +1671,25 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+                       /* Skip IP and UDP/GRE tunnel headers */
+                       offset = offset2 + ulen;
+                       /* Now we should be at the original IP header */
+-                      cih = skb_header_pointer(skb, offset, sizeof(_ciph),
+-                                               &_ciph);
+-                      if (cih && cih->version == 4 && cih->ihl >= 5 &&
+-                          iproto == IPPROTO_IPIP)
++                      if (iproto == IPPROTO_IPIP)
+                               tunnel = true;
+                       else
+                               return NF_ACCEPT;
+               }
+       }
+-      pd = ip_vs_proto_data_get(ipvs, cih->protocol);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph))
++              return NF_ACCEPT;
++      pd = ip_vs_proto_data_get(ipvs, ciph.protocol);
+       if (!pd)
+               return NF_ACCEPT;
+       pp = pd->pp;
++      cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       /* Is the embedded protocol header present? */
+       if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
+               return NF_ACCEPT;
+@@ -1694,9 +1697,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking incoming ICMP for");
+-      offset2 = offset;
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order.
+        * For IPIP/UDP/GRE tunnel this is error for request, not for reply.
+        */
+@@ -1726,11 +1726,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       }
+       if (tunnel) {
+-              unsigned int hlen_orig = cih->ihl * 4;
++              unsigned int hlen_orig = ciph.len - ciph.off;
+               __be32 info = ic->un.gateway;
+               __u8 type = ic->type;
+               __u8 code = ic->code;
++              offset2 = offset;
+               /* Update the MTU */
+               if (ic->type == ICMP_DEST_UNREACH &&
+                   ic->code == ICMP_FRAG_NEEDED) {
+diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
+index ac1827ef78949..7db74b2ea358c 100644
+--- a/net/netfilter/ipvs/ip_vs_xmit.c
++++ b/net/netfilter/ipvs/ip_vs_xmit.c
+@@ -1577,7 +1577,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+       if (skb_cow(skb, rt->dst.dev->hard_header_len))
+               goto tx_error;
+-      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports);
++      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports, ciph);
+       /* Another hack: avoid icmp_send in ip_fragment */
+       skb->ignore_df = 1;
+-- 
+2.53.0
+
diff --git a/queue-6.18/ipvs-return-the-csum-validation-for-forward-hook.patch b/queue-6.18/ipvs-return-the-csum-validation-for-forward-hook.patch
new file mode 100644 (file)
index 0000000..e599a57
--- /dev/null
@@ -0,0 +1,100 @@
+From cfce862a01d8cfd7f60dfc533eff1fa537741863 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:06 +0300
+Subject: ipvs: return the csum validation for forward hook
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 99609cb0aa789c8d071050ce8579989551882cc6 ]
+
+Sashiko notes that playing games with the skb dst and rt
+flags instead of providing hooknum is not a good idea
+when validating the checksums.
+
+Also, skipping checksum validation for FORWARD packets
+risk silent data corruption, even if the only user is
+the FTP-CMD packets coming from the real server.
+
+Sashiko also noticed that by using common checksum
+helper in the previous commit we actually fixed old bug
+where the TCP/UDP checksum for IPv6 on CHECKSUM_COMPLETE
+was not validated correctly.
+
+Fixes: e876b75b9020 ("ipvs: fix the checksum validations")
+Link: https://sashiko.dev/#/patchset/20260722211420.153933-1-pablo%40netfilter.org
+Link: https://sashiko.dev/#/patchset/20260727185024.67534-1-ja%40ssi.bg
+Link: https://sashiko.dev/#/patchset/20260728202520.59179-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h                   | 19 +++++--------------
+ net/netfilter/ipvs/ip_vs_proto_sctp.c |  2 +-
+ 2 files changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index cbad9c74a8868..d63d6459727d6 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -24,9 +24,7 @@
+ #include <linux/netfilter.h>          /* for union nf_inet_addr */
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>                       /* for struct ipv6hdr */
+-#include <net/route.h>
+ #include <net/ipv6.h>
+-#include <net/ip6_fib.h>
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ #include <net/netfilter/nf_conntrack.h>
+ #endif
+@@ -1753,30 +1751,23 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+       return csum_partial(diff, sizeof(diff), oldsum);
+ }
+-static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
++static inline bool ip_vs_checksum_needed(struct sk_buff *skb)
+ {
+       /* Checksum unnecessary or already validated? */
+       if (skb_csum_unnecessary(skb))
+               return false;
+-      /* LOCAL_OUT ? */
+-      if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
++      /* Locally generated ? */
++      if (!skb->dev)
+               return false;
+-      /* !LOCAL_IN (FORWARD) ? */
+-      if (af == AF_INET6) {
+-              if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
+-                      return false;
+-      } else {
+-              if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+-                      return false;
+-      }
+       return true;
+ }
+ static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
+                                              int offset, int proto, int af)
+ {
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return true;
++      /* Validate csum even for FORWARD */
+       return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+index 3dbd3096e1637..c80567c73469b 100644
+--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+@@ -193,7 +193,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+       struct sctphdr *sh;
+       __le32 cmp, val;
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return 1;
+       sh = (struct sctphdr *)(skb->data + sctphoff);
+       cmp = sh->checksum;
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-add-bare-bone-queue-configs.patch b/queue-6.18/net-add-bare-bone-queue-configs.patch
new file mode 100644 (file)
index 0000000..c2877e3
--- /dev/null
@@ -0,0 +1,328 @@
+From 2c798cddd711a9895fd7c51d5dc1b86ca62f64e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jan 2026 13:25:40 +0000
+Subject: net: add bare bone queue configs
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit efcb9a4d32d3d9b924642c086b868bfbb9a07c13 ]
+
+We'll need to pass extra parameters when allocating a queue for memory
+providers. Define a new structure for queue configurations, and pass it
+to qapi callbacks. It's empty for now, actual parameters will be added
+in following patches.
+
+Configurations should persist across resets, and for that they're
+default-initialised on device registration and stored in struct
+netdev_rx_queue. We also add a new qapi callback for defaulting a given
+config. It must be implemented if a driver wants to use queue configs
+and is optional otherwise.
+
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Stable-dep-of: d1000fd7995e ("bnxt: fix memory leak in bnxt_queue_mem_alloc error cases")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c       |  8 ++++++--
+ drivers/net/ethernet/google/gve/gve_main.c      |  9 ++++++---
+ .../net/ethernet/mellanox/mlx5/core/en_main.c   | 10 ++++++----
+ drivers/net/ethernet/meta/fbnic/fbnic_txrx.c    |  8 ++++++--
+ drivers/net/netdevsim/netdev.c                  |  7 +++++--
+ include/net/netdev_queues.h                     |  9 +++++++++
+ include/net/netdev_rx_queue.h                   |  2 ++
+ net/core/dev.c                                  | 17 +++++++++++++++++
+ net/core/netdev_rx_queue.c                      | 12 +++++++++---
+ 9 files changed, 66 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 1efd1f8776abe..f3fbbf188053c 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -15954,7 +15954,9 @@ static const struct netdev_stat_ops bnxt_stat_ops = {
+       .get_base_stats         = bnxt_get_base_stats,
+ };
+-static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
++static int bnxt_queue_mem_alloc(struct net_device *dev,
++                              struct netdev_queue_config *qcfg,
++                              void *qmem, int idx)
+ {
+       struct bnxt_rx_ring_info *rxr, *clone;
+       struct bnxt *bp = netdev_priv(dev);
+@@ -16120,7 +16122,9 @@ static void bnxt_copy_rx_ring(struct bnxt *bp,
+       dst->rx_agg_bmap = src->rx_agg_bmap;
+ }
+-static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
++static int bnxt_queue_start(struct net_device *dev,
++                          struct netdev_queue_config *qcfg,
++                          void *qmem, int idx)
+ {
+       struct bnxt *bp = netdev_priv(dev);
+       struct bnxt_rx_ring_info *rxr, *clone;
+diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
+index 030800776ead1..9751049849432 100644
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -2580,8 +2580,9 @@ static void gve_rx_queue_mem_free(struct net_device *dev, void *per_q_mem)
+               gve_rx_free_ring_dqo(priv, gve_per_q_mem, &cfg);
+ }
+-static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem,
+-                                int idx)
++static int gve_rx_queue_mem_alloc(struct net_device *dev,
++                                struct netdev_queue_config *qcfg,
++                                void *per_q_mem, int idx)
+ {
+       struct gve_priv *priv = netdev_priv(dev);
+       struct gve_rx_alloc_rings_cfg cfg = {0};
+@@ -2602,7 +2603,9 @@ static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem,
+       return err;
+ }
+-static int gve_rx_queue_start(struct net_device *dev, void *per_q_mem, int idx)
++static int gve_rx_queue_start(struct net_device *dev,
++                            struct netdev_queue_config *qcfg,
++                            void *per_q_mem, int idx)
+ {
+       struct gve_priv *priv = netdev_priv(dev);
+       struct gve_rx_ring *gve_per_q_mem;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index 7e754b72f889f..58e255910c43e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -5540,8 +5540,9 @@ struct mlx5_qmgmt_data {
+       struct mlx5e_channel_param cparam;
+ };
+-static int mlx5e_queue_mem_alloc(struct net_device *dev, void *newq,
+-                               int queue_index)
++static int mlx5e_queue_mem_alloc(struct net_device *dev,
++                               struct netdev_queue_config *qcfg,
++                               void *newq, int queue_index)
+ {
+       struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
+       struct mlx5e_priv *priv = netdev_priv(dev);
+@@ -5602,8 +5603,9 @@ static int mlx5e_queue_stop(struct net_device *dev, void *oldq, int queue_index)
+       return 0;
+ }
+-static int mlx5e_queue_start(struct net_device *dev, void *newq,
+-                           int queue_index)
++static int mlx5e_queue_start(struct net_device *dev,
++                           struct netdev_queue_config *qcfg,
++                           void *newq, int queue_index)
+ {
+       struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
+       struct mlx5e_priv *priv = netdev_priv(dev);
+diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+index 14885c3d70697..dbe0855ecb575 100644
+--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
++++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+@@ -2811,7 +2811,9 @@ void fbnic_napi_depletion_check(struct net_device *netdev)
+       fbnic_wrfl(fbd);
+ }
+-static int fbnic_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
++static int fbnic_queue_mem_alloc(struct net_device *dev,
++                               struct netdev_queue_config *qcfg,
++                               void *qmem, int idx)
+ {
+       struct fbnic_net *fbn = netdev_priv(dev);
+       const struct fbnic_q_triad *real;
+@@ -2863,7 +2865,9 @@ static void __fbnic_nv_restart(struct fbnic_net *fbn,
+               netif_wake_subqueue(fbn->netdev, nv->qt[i].sub0.q_idx);
+ }
+-static int fbnic_queue_start(struct net_device *dev, void *qmem, int idx)
++static int fbnic_queue_start(struct net_device *dev,
++                           struct netdev_queue_config *qcfg,
++                           void *qmem, int idx)
+ {
+       struct fbnic_net *fbn = netdev_priv(dev);
+       struct fbnic_napi_vector *nv;
+diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
+index 06446b03cd9bc..7a8e17bf46bdb 100644
+--- a/drivers/net/netdevsim/netdev.c
++++ b/drivers/net/netdevsim/netdev.c
+@@ -760,7 +760,9 @@ struct nsim_queue_mem {
+ };
+ static int
+-nsim_queue_mem_alloc(struct net_device *dev, void *per_queue_mem, int idx)
++nsim_queue_mem_alloc(struct net_device *dev,
++                   struct netdev_queue_config *qcfg,
++                   void *per_queue_mem, int idx)
+ {
+       struct nsim_queue_mem *qmem = per_queue_mem;
+       struct netdevsim *ns = netdev_priv(dev);
+@@ -809,7 +811,8 @@ static void nsim_queue_mem_free(struct net_device *dev, void *per_queue_mem)
+ }
+ static int
+-nsim_queue_start(struct net_device *dev, void *per_queue_mem, int idx)
++nsim_queue_start(struct net_device *dev, struct netdev_queue_config *qcfg,
++               void *per_queue_mem, int idx)
+ {
+       struct nsim_queue_mem *qmem = per_queue_mem;
+       struct netdevsim *ns = netdev_priv(dev);
+diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
+index 541e7d9853b1b..f6f1f71a24e15 100644
+--- a/include/net/netdev_queues.h
++++ b/include/net/netdev_queues.h
+@@ -14,6 +14,9 @@ struct netdev_config {
+       u8      hds_config;
+ };
++struct netdev_queue_config {
++};
++
+ /* See the netdev.yaml spec for definition of each statistic */
+ struct netdev_queue_stats_rx {
+       u64 bytes;
+@@ -130,6 +133,8 @@ void netdev_stat_queue_sum(struct net_device *netdev,
+  * @ndo_queue_get_dma_dev: Get dma device for zero-copy operations to be used
+  *                       for this queue. Return NULL on error.
+  *
++ * @ndo_default_qcfg: Populate queue config struct with defaults. Optional.
++ *
+  * Note that @ndo_queue_mem_alloc and @ndo_queue_mem_free may be called while
+  * the interface is closed. @ndo_queue_start and @ndo_queue_stop will only
+  * be called for an interface which is open.
+@@ -137,16 +142,20 @@ void netdev_stat_queue_sum(struct net_device *netdev,
+ struct netdev_queue_mgmt_ops {
+       size_t  ndo_queue_mem_size;
+       int     (*ndo_queue_mem_alloc)(struct net_device *dev,
++                                     struct netdev_queue_config *qcfg,
+                                      void *per_queue_mem,
+                                      int idx);
+       void    (*ndo_queue_mem_free)(struct net_device *dev,
+                                     void *per_queue_mem);
+       int     (*ndo_queue_start)(struct net_device *dev,
++                                 struct netdev_queue_config *qcfg,
+                                  void *per_queue_mem,
+                                  int idx);
+       int     (*ndo_queue_stop)(struct net_device *dev,
+                                 void *per_queue_mem,
+                                 int idx);
++      void    (*ndo_default_qcfg)(struct net_device *dev,
++                                  struct netdev_queue_config *qcfg);
+       struct device * (*ndo_queue_get_dma_dev)(struct net_device *dev,
+                                                int idx);
+ };
+diff --git a/include/net/netdev_rx_queue.h b/include/net/netdev_rx_queue.h
+index 8cdcd138b33f2..cfa72c4853876 100644
+--- a/include/net/netdev_rx_queue.h
++++ b/include/net/netdev_rx_queue.h
+@@ -7,6 +7,7 @@
+ #include <linux/sysfs.h>
+ #include <net/xdp.h>
+ #include <net/page_pool/types.h>
++#include <net/netdev_queues.h>
+ /* This structure contains an instance of an RX queue. */
+ struct netdev_rx_queue {
+@@ -27,6 +28,7 @@ struct netdev_rx_queue {
+       struct xsk_buff_pool            *pool;
+ #endif
+       struct napi_struct              *napi;
++      struct netdev_queue_config      qcfg;
+       struct pp_memory_provider_params mp_params;
+ } ____cacheline_aligned_in_smp;
+diff --git a/net/core/dev.c b/net/core/dev.c
+index a83083e8761b1..e4ea5615e81ea 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -11223,6 +11223,21 @@ static void netdev_free_phy_link_topology(struct net_device *dev)
+       }
+ }
++static void init_rx_queue_cfgs(struct net_device *dev)
++{
++      const struct netdev_queue_mgmt_ops *qops = dev->queue_mgmt_ops;
++      struct netdev_rx_queue *rxq;
++      int i;
++
++      if (!qops || !qops->ndo_default_qcfg)
++              return;
++
++      for (i = 0; i < dev->num_rx_queues; i++) {
++              rxq = __netif_get_rx_queue(dev, i);
++              qops->ndo_default_qcfg(dev, &rxq->qcfg);
++      }
++}
++
+ /**
+  * register_netdevice() - register a network device
+  * @dev: device to register
+@@ -11268,6 +11283,8 @@ int register_netdevice(struct net_device *dev)
+       if (!dev->name_node)
+               goto out;
++      init_rx_queue_cfgs(dev);
++
+       /* Init, if this function is available */
+       if (dev->netdev_ops->ndo_init) {
+               ret = dev->netdev_ops->ndo_init(dev);
+diff --git a/net/core/netdev_rx_queue.c b/net/core/netdev_rx_queue.c
+index c7d9341b76307..f18147b478688 100644
+--- a/net/core/netdev_rx_queue.c
++++ b/net/core/netdev_rx_queue.c
+@@ -22,6 +22,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+ {
+       struct netdev_rx_queue *rxq = __netif_get_rx_queue(dev, rxq_idx);
+       const struct netdev_queue_mgmt_ops *qops = dev->queue_mgmt_ops;
++      struct netdev_queue_config qcfg;
+       void *new_mem, *old_mem;
+       int err;
+@@ -31,6 +32,10 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+       netdev_assert_locked(dev);
++      memset(&qcfg, 0, sizeof(qcfg));
++      if (qops->ndo_default_qcfg)
++              qops->ndo_default_qcfg(dev, &qcfg);
++
+       new_mem = kvzalloc(qops->ndo_queue_mem_size, GFP_KERNEL);
+       if (!new_mem)
+               return -ENOMEM;
+@@ -41,7 +46,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+               goto err_free_new_mem;
+       }
+-      err = qops->ndo_queue_mem_alloc(dev, new_mem, rxq_idx);
++      err = qops->ndo_queue_mem_alloc(dev, &qcfg, new_mem, rxq_idx);
+       if (err)
+               goto err_free_old_mem;
+@@ -54,7 +59,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+               if (err)
+                       goto err_free_new_queue_mem;
+-              err = qops->ndo_queue_start(dev, new_mem, rxq_idx);
++              err = qops->ndo_queue_start(dev, &qcfg, new_mem, rxq_idx);
+               if (err)
+                       goto err_start_queue;
+       } else {
+@@ -66,6 +71,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+       kvfree(old_mem);
+       kvfree(new_mem);
++      rxq->qcfg = qcfg;
+       return 0;
+ err_start_queue:
+@@ -76,7 +82,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+        * WARN if we fail to recover the old rx queue, and at least free
+        * old_mem so we don't also leak that.
+        */
+-      if (qops->ndo_queue_start(dev, old_mem, rxq_idx)) {
++      if (qops->ndo_queue_start(dev, &rxq->qcfg, old_mem, rxq_idx)) {
+               WARN(1,
+                    "Failed to restart old queue in error path. RX queue %d may be unhealthy.",
+                    rxq_idx);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch b/queue-6.18/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
new file mode 100644 (file)
index 0000000..ce57196
--- /dev/null
@@ -0,0 +1,81 @@
+From 29cdbab9bcd2e7dba7f145c95ccf34d98b3ce8f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 13:15:08 +0000
+Subject: net/atm: fix slab-out-of-bounds read in vcc_setsockopt()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d0c80dbb970439bd2eeb0e5effff8c16a5f4e1e3 ]
+
+vcc_setsockopt() contained an ineffective optlen check:
+  if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+      return -EINVAL;
+
+If __SO_LEVEL_MATCH(optname, level) evaluated to false (e.g. if the caller
+passed a mismatched level), the length check optlen != __SO_SIZE(optname)
+was short-circuited and bypassed. Execution then fell through to switch(optname),
+calling copy_from_sockptr() assuming optval contained sufficient space.
+
+Furthermore, even if level matched, a cgroup BPF setsockopt filter could shrink
+optlen after entry. Because copy_from_sockptr() on kernel pointers uses memcpy(),
+this leads to a KASAN slab-out-of-bounds read when optlen is smaller than the
+expected structure size.
+
+Fix this by using copy_safe_from_sockptr(), which unconditionally validates
+that optlen is at least the expected size before copying. Also change the local
+'value' variable type from 'unsigned long' to 'int' so that SO_SETCLP matches
+its sizeof(int) ABI encoding on 64-bit systems.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+53ecc09fb81df10ef4de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=53ecc09fb81df10ef4de
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260805131508.3227331-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/atm/common.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/net/atm/common.c b/net/atm/common.c
+index f4c6e0131c921..f4be6cb220861 100644
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+                  sockptr_t optval, unsigned int optlen)
+ {
+       struct atm_vcc *vcc;
+-      unsigned long value;
++      int value;
+       int error;
+       if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+@@ -772,8 +772,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+       {
+               struct atm_qos qos;
+-              if (copy_from_sockptr(&qos, optval, sizeof(qos)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&qos, sizeof(qos), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               error = check_qos(&qos);
+               if (error)
+                       return error;
+@@ -786,8 +788,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+               return 0;
+       }
+       case SO_SETCLP:
+-              if (copy_from_sockptr(&value, optval, sizeof(value)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&value, sizeof(value), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               if (value)
+                       vcc->atm_options |= ATM_ATMOPT_CLP;
+               else
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-6.18/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..b8b1a7c
--- /dev/null
@@ -0,0 +1,42 @@
+From f85fc2f0b87800e63b00f5d0247d15aa328d45ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index e3e7f2270560c..02282dc86faf4 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1282,7 +1282,6 @@ static void hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-hns3-fix-speed-configuration-residue-after-drive.patch b/queue-6.18/net-hns3-fix-speed-configuration-residue-after-drive.patch
new file mode 100644 (file)
index 0000000..071e42b
--- /dev/null
@@ -0,0 +1,76 @@
+From 14b6ecce397d8f08fa8d54bac30a5a21f0852567 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 17:30:36 +0800
+Subject: net: hns3: fix speed configuration residue after driver reload
+
+From: Jijie Shao <shaojijie@huawei.com>
+
+[ Upstream commit 3860d8748af315bfee6fe669fddc1fc17d3214db ]
+
+After setting a 100G optical port to 40G via ethtool and reloading
+the driver, the port remains at 40G instead of reverting to the
+firmware default speed of 100G.
+
+The commit referenced in Fixes: added two overwrites in
+hclge_init_ae_dev() for non-copper media, so that optical ports
+connected to forced-mode remotes inherit the firmware-preset
+autoneg and speed instead of the hardcoded defaults:
+
+  req_autoneg = mac.autoneg
+  req_speed   = mac.speed         (when autoneg disabled)
+
+The autoneg overwrite keeps existing behavior:
+hclge_set_autoneg_speed_dup() already uses mac.autoneg (not
+req_autoneg) since it was introduced, so autoneg inheritance from
+firmware was already in place. This part is kept.
+
+The speed overwrite, however, introduces the residue: mac.speed
+reflects whatever was last programmed into the MAC, and after unload
+firmware does not restore the MAC speed to the flash default. So if
+the user changed speed via ethtool in a prior load, mac.speed still
+carries that value on reload and req_speed inherits it.
+
+Fix by dropping the req_speed overwrite only. req_speed keeps the
+firmware default value set in hclge_configure() (cfg.default_speed),
+so a reload reverts the speed to default, matching the expectation
+that a driver reload resets link configuration.
+
+Trade-off: on optical ports whose firmware default speed does not
+match a forced-mode remote, reload now drops the link and the user
+must re-apply ethtool configuration. This is acceptable: a driver
+reload is expected to reset link configuration, not to inherit
+runtime state from before unload. The autoneg inheritance is left
+in place as established behavior; changing it is out of scope for
+this patch and would itself be a user-perceivable behavior change.
+
+Fixes: d9d349c4e8a0 ("net: hns3: differentiate autoneg default values between copper and fiber")
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260724093036.426631-1-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 7f174453928c1..02fee71c20886 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -11930,12 +11930,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+       if (ret)
+               goto err_ptp_uninit;
+-      if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER) {
++      if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER)
+               hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg;
+-              if (hdev->hw.mac.autoneg == AUTONEG_DISABLE &&
+-                  hdev->hw.mac.speed != SPEED_UNKNOWN)
+-                      hdev->hw.mac.req_speed = hdev->hw.mac.speed;
+-      }
+       ret = hclge_set_autoneg_speed_dup(hdev);
+       if (ret) {
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-6.18/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..e34c682
--- /dev/null
@@ -0,0 +1,134 @@
+From c407f2d60c0f5a44fa5e60229849286d9a2f44e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 0b82a6a133d6c..74f68b70ad1c1 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1025,13 +1025,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1073,7 +1071,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1084,7 +1082,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       if (!tracer->str_db.loaded)
+@@ -1134,7 +1132,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mutex_lock(&tracer->state_lock);
+@@ -1163,7 +1161,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1215,7 +1213,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-mlx5e-fix-bql-reset-on-sq-re-activation.patch b/queue-6.18/net-mlx5e-fix-bql-reset-on-sq-re-activation.patch
new file mode 100644 (file)
index 0000000..4fee36f
--- /dev/null
@@ -0,0 +1,58 @@
+From 6371349ea2dfbcc3d33de7c97292ee4e75f9ccea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 16:47:29 -0700
+Subject: net/mlx5e: fix BQL reset on SQ re-activation
+
+From: Bobby Eshleman <bobbyeshleman@meta.com>
+
+[ Upstream commit e7386770be1bf810bcd6af39d1e4bfeab3408430 ]
+
+mlx5e_queue_start() deactivates and re-activates all channels but closes
+only the queue being restarted. mlx5e_activate_txqsq() then
+unconditionally calls netdev_tx_reset_queue(), zeroing the BQL counters
+of channels that kept their in-flight TX WQEs. The next completion then
+over-charges and trips the BUG_ON() in dql_completed():
+
+  kernel BUG at lib/dynamic_queue_limits.c:99!
+  RIP: 0010:dql_completed+0x23d/0x280
+  Call Trace:
+   <IRQ>
+   mlx5e_poll_tx_cq+0x668/0xa60
+   mlx5e_napi_poll+0x5b/0x7b0
+   net_rx_action+0x15a/0x580
+
+Reset BQL only when the SQ has no bytes in flight (sq->cc == sq->pc).
+
+In the case that reset is skipped, the outstanding WQEs will eventually
+complete and rebalance the dql. The dql->limit is carried across the
+reset.
+
+Fixes: b2588ea40ec9 ("net/mlx5e: Implement queue mgmt ops and single channel swap")
+Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260803-mlx5-bql-v3-1-a30d4c66fe1d@meta.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 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 58e255910c43e..a7d84b540488a 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -1926,8 +1926,10 @@ int mlx5e_open_txqsq(struct mlx5e_channel *c, u32 tisn, int txq_ix,
+ void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
+ {
+       sq->txq = netdev_get_tx_queue(sq->netdev, sq->txq_ix);
++      /* Reset BQL only when the SQ has no bytes in flight. */
++      if (sq->cc == sq->pc)
++              netdev_tx_reset_queue(sq->txq);
+       set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
+-      netdev_tx_reset_queue(sq->txq);
+       netif_tx_start_queue(sq->txq);
+       netif_queue_set_napi(sq->netdev, sq->txq_ix, NETDEV_QUEUE_TYPE_TX, sq->cq.napi);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch b/queue-6.18/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
new file mode 100644 (file)
index 0000000..b65af84
--- /dev/null
@@ -0,0 +1,100 @@
+From d513e5a9d3274974e85faba87cf8adaca7eb6619 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 07:43:38 +0300
+Subject: net/mlx5e: TC, Check if flow is PEER before acquiring devcom lock
+
+From: Shay Drory <shayd@nvidia.com>
+
+[ Upstream commit 6ddfba2ea98db21b001e0e5c472499156224650c ]
+
+In case __mlx5e_add_fdb_flow() fails in lower levels, the flow is
+deleted via mlx5e_tc_del_flow(), and mlx5e_tc_del_flow() is acquiring
+ESW devcom lock without condition. In addition, in case of peer_flow,
+__mlx5e_add_fdb_flow() is called while holding ESW devcom comp lock.
+This results in an AA deadlock.
+
+To fix this, introduce a new PEER flag that is set on flows created as
+peer flows (the duplicate flows on peer devices), and check it in
+mlx5e_tc_del_flow() before acquiring ESW devcom lock.
+
+Lockdep splat:
+============================================
+WARNING: possible recursive locking detected
+============================================
+ Possible unsafe locking scenario:
+       CPU0
+       ----
+  lock(&comp->lock_key#2);
+  lock(&comp->lock_key#2);
+ *** DEADLOCK ***
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x69/0xa0
+ print_deadlock_bug.cold+0xbd/0xca
+ __lock_acquire+0x1671/0x2ec0
+ lock_acquire+0x10e/0x2e0
+ down_read+0x95/0x430
+ mlx5_devcom_for_each_peer_begin+0x4e/0xe0 [mlx5_core]
+ mlx5e_tc_del_flow+0x11d/0xa70 [mlx5_core]
+ mlx5e_flow_put+0x99/0x100 [mlx5_core]
+ __mlx5e_add_fdb_flow+0x409/0xf00 [mlx5_core]
+ mlx5e_configure_flower+0x2a86/0x4100 [mlx5_core]
+ mlx5e_rep_setup_tc_cls_flower+0x12f/0x1b0 [mlx5_core]
+ mlx5e_rep_setup_tc_cb+0x153/0x750 [mlx5_core]
+ tc_setup_cb_add+0x1dc/0x470
+ fl_change+0x2f4d/0x626d [cls_flower]
+ tc_new_tfilter+0x79b/0x2310
+ rtnetlink_rcv_msg+0x778/0xad0
+ do_syscall_64+0x70/0x960
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ </TASK>
+
+Fixes: 04de7dda7394 ("net/mlx5e: Infrastructure for duplicated offloading of TC flows")
+Signed-off-by: Shay Drory <shayd@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260728044338.2271143-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h | 1 +
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c      | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+index efb34de4cb7ad..692ac2f21d94e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+@@ -30,6 +30,7 @@ enum {
+       MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 9,
+       MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 10,
+       MLX5E_TC_FLOW_FLAG_USE_ACT_STATS         = MLX5E_TC_FLOW_BASE + 11,
++      MLX5E_TC_FLOW_FLAG_PEER                  = MLX5E_TC_FLOW_BASE + 12,
+ };
+ struct mlx5e_tc_flow_parse_attr {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index ebea43c235cc3..e2de3a9a647c3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -2165,7 +2165,8 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
+       if (mlx5e_is_eswitch_flow(flow)) {
+               struct mlx5_devcom_comp_dev *devcom = flow->priv->mdev->priv.eswitch->devcom;
+-              if (!mlx5_devcom_for_each_peer_begin(devcom)) {
++              if (flow_flag_test(flow, PEER) ||
++                  !mlx5_devcom_for_each_peer_begin(devcom)) {
+                       mlx5e_tc_del_fdb_flow(priv, flow);
+                       return;
+               }
+@@ -4609,6 +4610,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
+       else
+               in_mdev = priv->mdev;
++      flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_PEER);
+       parse_attr = flow->attr->parse_attr;
+       peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
+                                        parse_attr->filter_dev,
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-6.18/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..0ade155
--- /dev/null
@@ -0,0 +1,60 @@
+From 37898435c35b4fcd5c4eb9d33eb0d846f9476bbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index 2f872d064396d..8cc538358f6a3 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-6.18/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..82eed75
--- /dev/null
@@ -0,0 +1,78 @@
+From f05ba68c48e829e2d513ed9d4047af14e2f19b6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 66366982f6044..46c1d66aad8c3 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -889,8 +889,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -910,8 +908,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -926,6 +922,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-pass-queue-rx-page-size-from-memory-provider.patch b/queue-6.18/net-pass-queue-rx-page-size-from-memory-provider.patch
new file mode 100644 (file)
index 0000000..15d1bd0
--- /dev/null
@@ -0,0 +1,111 @@
+From 5bdf7ae5af6e7417d271955d8193c1dde850d7ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jan 2026 13:25:40 +0000
+Subject: net: pass queue rx page size from memory provider
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit c0b709bf438ba9d197d369f55e4a97603fd4a705 ]
+
+Allow memory providers to configure rx queues with a custom receive
+page size. It's passed in struct pp_memory_provider_params, which is
+copied into the queue, so it's preserved across queue restarts. Then,
+it's propagated to the driver in a new queue config parameter.
+
+Drivers should explicitly opt into using it by setting
+QCFG_RX_PAGE_SIZE, in which case they should implement ndo_default_qcfg,
+validate the size on queue restart and honour the current config in case
+of a reset.
+
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Stable-dep-of: d1000fd7995e ("bnxt: fix memory leak in bnxt_queue_mem_alloc error cases")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netdev_queues.h   | 10 ++++++++++
+ include/net/page_pool/types.h |  1 +
+ net/core/netdev_rx_queue.c    |  9 +++++++++
+ 3 files changed, 20 insertions(+)
+
+diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
+index f6f1f71a24e15..feca25131930b 100644
+--- a/include/net/netdev_queues.h
++++ b/include/net/netdev_queues.h
+@@ -15,6 +15,7 @@ struct netdev_config {
+ };
+ struct netdev_queue_config {
++      u32     rx_page_size;
+ };
+ /* See the netdev.yaml spec for definition of each statistic */
+@@ -114,6 +115,11 @@ void netdev_stat_queue_sum(struct net_device *netdev,
+                          int tx_start, int tx_end,
+                          struct netdev_queue_stats_tx *tx_sum);
++enum {
++      /* The queue checks and honours the page size qcfg parameter */
++      QCFG_RX_PAGE_SIZE       = 0x1,
++};
++
+ /**
+  * struct netdev_queue_mgmt_ops - netdev ops for queue management
+  *
+@@ -135,6 +141,8 @@ void netdev_stat_queue_sum(struct net_device *netdev,
+  *
+  * @ndo_default_qcfg: Populate queue config struct with defaults. Optional.
+  *
++ * @supported_params: Bitmask of supported parameters, see QCFG_*.
++ *
+  * Note that @ndo_queue_mem_alloc and @ndo_queue_mem_free may be called while
+  * the interface is closed. @ndo_queue_start and @ndo_queue_stop will only
+  * be called for an interface which is open.
+@@ -158,6 +166,8 @@ struct netdev_queue_mgmt_ops {
+                                   struct netdev_queue_config *qcfg);
+       struct device * (*ndo_queue_get_dma_dev)(struct net_device *dev,
+                                                int idx);
++
++      unsigned int supported_params;
+ };
+ bool netif_rxq_has_unreadable_mp(struct net_device *dev, int idx);
+diff --git a/include/net/page_pool/types.h b/include/net/page_pool/types.h
+index fb4f03ccd6156..cdd95477af7a2 100644
+--- a/include/net/page_pool/types.h
++++ b/include/net/page_pool/types.h
+@@ -161,6 +161,7 @@ struct memory_provider_ops;
+ struct pp_memory_provider_params {
+       void *mp_priv;
+       const struct memory_provider_ops *mp_ops;
++      u32 rx_page_size;
+ };
+ struct page_pool {
+diff --git a/net/core/netdev_rx_queue.c b/net/core/netdev_rx_queue.c
+index f18147b478688..485bdb7447b99 100644
+--- a/net/core/netdev_rx_queue.c
++++ b/net/core/netdev_rx_queue.c
+@@ -30,12 +30,21 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+           !qops->ndo_queue_mem_alloc || !qops->ndo_queue_start)
+               return -EOPNOTSUPP;
++      if (WARN_ON_ONCE(qops->supported_params && !qops->ndo_default_qcfg))
++              return -EINVAL;
++
+       netdev_assert_locked(dev);
+       memset(&qcfg, 0, sizeof(qcfg));
+       if (qops->ndo_default_qcfg)
+               qops->ndo_default_qcfg(dev, &qcfg);
++      if (rxq->mp_params.rx_page_size) {
++              if (!(qops->supported_params & QCFG_RX_PAGE_SIZE))
++                      return -EOPNOTSUPP;
++              qcfg.rx_page_size = rxq->mp_params.rx_page_size;
++      }
++
+       new_mem = kvzalloc(qops->ndo_queue_mem_size, GFP_KERNEL);
+       if (!new_mem)
+               return -ENOMEM;
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-prestera-validate-firmware-header-length.patch b/queue-6.18/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..bc15220
--- /dev/null
@@ -0,0 +1,42 @@
+From 2ef5ff19fdf14ff7d193831ae8ca6e2d903c7b63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index 3e13322470da6..bacc869551dfd 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -684,6 +684,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-reduce-indent-of-struct-netdev_queue_mgmt_ops-me.patch b/queue-6.18/net-reduce-indent-of-struct-netdev_queue_mgmt_ops-me.patch
new file mode 100644 (file)
index 0000000..b13135d
--- /dev/null
@@ -0,0 +1,64 @@
+From 2209506efea0bd9b6b24d96a485326140d2f89f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 15:28:15 -0700
+Subject: net: reduce indent of struct netdev_queue_mgmt_ops members
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 92d76cf96dcbc3c58daa84dbbf71a3ca8d9de53d ]
+
+Trivial change, reduce the indent. I think the original is copied
+from real NDOs. It's unnecessarily deep, makes passing struct args
+problematic.
+
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Stable-dep-of: d1000fd7995e ("bnxt: fix memory leak in bnxt_queue_mem_alloc error cases")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netdev_queues.h | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
+index cd00e0406cf46..541e7d9853b1b 100644
+--- a/include/net/netdev_queues.h
++++ b/include/net/netdev_queues.h
+@@ -135,20 +135,20 @@ void netdev_stat_queue_sum(struct net_device *netdev,
+  * be called for an interface which is open.
+  */
+ struct netdev_queue_mgmt_ops {
+-      size_t                  ndo_queue_mem_size;
+-      int                     (*ndo_queue_mem_alloc)(struct net_device *dev,
+-                                                     void *per_queue_mem,
+-                                                     int idx);
+-      void                    (*ndo_queue_mem_free)(struct net_device *dev,
+-                                                    void *per_queue_mem);
+-      int                     (*ndo_queue_start)(struct net_device *dev,
+-                                                 void *per_queue_mem,
+-                                                 int idx);
+-      int                     (*ndo_queue_stop)(struct net_device *dev,
+-                                                void *per_queue_mem,
+-                                                int idx);
+-      struct device *         (*ndo_queue_get_dma_dev)(struct net_device *dev,
+-                                                       int idx);
++      size_t  ndo_queue_mem_size;
++      int     (*ndo_queue_mem_alloc)(struct net_device *dev,
++                                     void *per_queue_mem,
++                                     int idx);
++      void    (*ndo_queue_mem_free)(struct net_device *dev,
++                                    void *per_queue_mem);
++      int     (*ndo_queue_start)(struct net_device *dev,
++                                 void *per_queue_mem,
++                                 int idx);
++      int     (*ndo_queue_stop)(struct net_device *dev,
++                                void *per_queue_mem,
++                                int idx);
++      struct device * (*ndo_queue_get_dma_dev)(struct net_device *dev,
++                                               int idx);
+ };
+ bool netif_rxq_has_unreadable_mp(struct net_device *dev, int idx);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-6.18/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..a7eb6d5
--- /dev/null
@@ -0,0 +1,45 @@
+From 2680d67ddd192bd42d887bbe837c73e558f2bb65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 5a658606c50e8..b69c574c20ad3 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -786,7 +786,6 @@ bool sk_mc_loop(const struct sock *sk)
+               return inet6_test_bit(MC6_LOOP, sk);
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch b/queue-6.18/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
new file mode 100644 (file)
index 0000000..86eb383
--- /dev/null
@@ -0,0 +1,116 @@
+From 76d1acd39b44c4fa0ec75f9a04f60e933b7cdcd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 08:56:32 -0400
+Subject: net/sched: cls_api: Always acquire rtnl_lock when destroying locked
+ classifiers
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit a347304b2ca1a5377d5bd2d8a72e4b4f12afe648 ]
+
+Another challenge with unlocked filters.
+There is a short window in tc_new_tfilter where a tcf_proto can be found
+and briefly referenced by a totally unrelated, unlocked classifier's request
+and cause a race.
+
+Feng created a poc which created this race with two threads, one creating a
+u32 filter and other a flower filter in the same chain/prio:
+
+1. Both threads enter tc_new_tfilter, both find the chain empty, both
+   drop filter_chain_lock
+2. u32 finishes tcf_proto_create("u32") first, calls
+   tcf_chain_tp_insert_unique() -> inserts u32_tp into the chain
+3. flower finishes tcf_proto_create("flower") later, calls
+   tcf_chain_tp_insert_unique() -> tcf_chain_tp_find() now sees u32_tp
+   already there, takes a reference on it, destroys flower's own tp_new
+   and returns u32_tp to the caller.
+
+Flower then hits the kind mismatch check (because it requested for kind
+"flower" but tp->ops->kind is "u32") and goes through the errout path
+which calls tcf_proto_put() on u32_tp. If the u32 thread has already
+gone through its own errout (its change() call failed on the PoC's empty
+options) and dropped its create and insert refs, flower's put is the
+last one and drops u32_tp's refcnt to zero.
+
+At this point tp->ops->destroy() runs in a context that never took
+rtnl_lock. When that happens, it might cause a UAF like the following
+(illustrated by the PoC):
+
+[  +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
+[  +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524
+
+  Call Trace:
+   u32_init (net/sched/cls_u32.c:393)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Allocated by task 526:
+   u32_init (net/sched/cls_u32.c:378)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Freed by task 522:
+   kfree
+   u32_destroy (net/sched/cls_u32.c:662)
+   tcf_proto_destroy (net/sched/cls_api.c:446)
+   tcf_proto_put (net/sched/cls_api.c:459)
+   tc_new_tfilter (net/sched/cls_api.c:2459)
+
+Fix this by having tcf_proto_destroy() take rtnl_lock around
+tp->ops->destroy() for locked classifiers whenever rtnl is not held.
+
+To explain why I used a temp variable "not_lockless" I'd like to point to a
+semi-related note on rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (adding here
+for future cleanup if deemed necessary):
+The rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are
+redundant sources of truth for whether rtnl_lock is held. Among the nine
+classifier destroy(..rtnl_held..) callbacks, only flower consults the
+rtnl_held parameter which it propagates to tc_setup_cb_destroy()
+and tc_setup_cb_call(). The other eight (u32, flow, bpf, cgroup, route, basic,
+fw, mall) ignore it entirely;-> those that call tc_setup_cb_destroy()
+(u32, bpf, mall) hardcode true always instead of forwarding the parameter.
+
+A future cleanup should remove the rtnl_held parameter from the destroy callback
+signature entirely and have callers rely solely on their knowledge whether
+they are running in an unlocked context.
+
+Fixes: 12db03b65c2b ("net: sched: extend proto ops to support unlocked classifiers")
+Reported-by: Feng Xue <feng.xue@outlook.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260801125632.360365-1-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_api.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 3b0a438977cd5..21a70cc9940ce 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -443,7 +443,22 @@ static void tcf_chain_put(struct tcf_chain *chain);
+ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
+                             bool sig_destroy, struct netlink_ext_ack *extack)
+ {
+-      tp->ops->destroy(tp, rtnl_held, extack);
++      /* A locked classifier's destroy callback (e.g. u32_destroy) uses
++       * rtnl_dereference() and mutates shared structures (e.g. the
++       * tc_u_common hash list) that are only safe under rtnl_lock. When an
++       * unlocked classifier's request (e.g. flower on ingress) loses the
++       * tcf_chain_tp_insert_unique() race and ends up dropping the last
++       * reference on a locked classifier's proto, destroy() would run
++       * without rtnl held. Take it here in that case.
++       */
++      bool not_lockless = !rtnl_held &&
++              !(tp->ops->flags & TCF_PROTO_OPS_DOIT_UNLOCKED);
++
++      if (not_lockless)
++              rtnl_lock();
++      tp->ops->destroy(tp, rtnl_held || not_lockless, extack);
++      if (not_lockless)
++              rtnl_unlock();
+       tcf_proto_count_usesw(tp, false);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-6.18/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..480d2d8
--- /dev/null
@@ -0,0 +1,142 @@
+From 0a82a2f52684cf16105c80364e1c48e4b891c7f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index b9c58c040c305..38469cdcb22d6 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -52,6 +52,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -66,9 +67,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -81,9 +84,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -297,6 +302,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -307,6 +319,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -334,11 +351,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -558,7 +575,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-6.18/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..7fdaf79
--- /dev/null
@@ -0,0 +1,50 @@
+From e5db135a91ef6f4e032eca151060bac30fa41a77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index c19eeed7e7cfb..e03fe7096b357 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1268,7 +1268,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ntohs(ipv6h_check->payload_len);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-6.18/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..1637000
--- /dev/null
@@ -0,0 +1,57 @@
+From 8273786ed9a3f5ae6704d9f909ca84fb058f2c60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index f865c58c3aa77..28873ec06e3c1 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1927,7 +1927,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch b/queue-6.18/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
new file mode 100644 (file)
index 0000000..cee78c9
--- /dev/null
@@ -0,0 +1,71 @@
+From 5bb2833c886f1d22a54be87ab492b935118e4dd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 09:07:01 +0200
+Subject: net/smc: fix TOCTOU race between smc_listen_out() and listener close
+
+From: Sidraya Jayagond <sidraya@linux.ibm.com>
+
+[ Upstream commit 185a4caeecabc150106deda1da170b09f2ad803f ]
+
+smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
+then acquires lock_sock_nested() only after the check passes. This
+opens a window where smc_close_active() can transition the listener
+to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
+queue, and release the lock, all between the lockless read and the
+delayed lock acquisition:
+
+  smc_listen_work (smc_hs_wq)          smc_close_active()
+  -------------------------------      -------------------------
+  release_sock(child)
+  if (sk_state == SMC_LISTEN) TRUE
+                                        lock_sock(listener)
+                                        sk_state = SMC_CLOSED
+                                        smc_close_cleanup_listen()
+                                        release_sock(listener)
+                                        flush_work(tcp_listen_work)
+  lock_sock_nested(listener)
+  smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
+
+smc_close_active() flushes only tcp_listen_work. Work items already
+dispatched onto smc_hs_wq for the CLC handshake continue running
+unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
+is never released, so the child smc_sock, its clcsock, and the
+reference all leak. A remote peer that opens TCP connections while the
+server calls close() can exhaust kernel memory.
+
+Move lock_sock_nested() to before the sk_state check so that the test
+and the enqueue are atomic under the listener lock.
+
+Fixes: fd57770dd198 ("net/smc: wait for pending work before clcsock release_sock")
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260803070701.126339-1-sidraya@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 47963eda478f6..bc7b4a33b7261 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1935,11 +1935,12 @@ static void smc_listen_out(struct smc_sock *new_smc)
+               atomic_dec(&lsmc->queued_smc_hs);
+       release_sock(newsmcsk); /* lock in smc_listen_work() */
++      lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+       if (lsmc->sk.sk_state == SMC_LISTEN) {
+-              lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+               smc_accept_enqueue(&lsmc->sk, newsmcsk);
+               release_sock(&lsmc->sk);
+       } else { /* no longer listening */
++              release_sock(&lsmc->sk);
+               smc_close_non_accepted(newsmcsk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-stmmac-resume-phy-before-hardware-setup-when-ope.patch b/queue-6.18/net-stmmac-resume-phy-before-hardware-setup-when-ope.patch
new file mode 100644 (file)
index 0000000..a6c4dca
--- /dev/null
@@ -0,0 +1,79 @@
+From 7fd83da1105a04ce07766dff932c16e2dfb38723 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 11:51:56 +0200
+Subject: net: stmmac: resume PHY before hardware setup when opening the
+ interface
+
+From: Stefan Agner <stefan@agner.ch>
+
+[ Upstream commit 06232cb44bc8e81adc2f1d40a01bed830b607ea2 ]
+
+Since the referenced commit, changing the MTU on a running interface no
+longer disconnects and reconnects the PHY; __stmmac_release() merely
+stops phylink, which also suspends the PHY (BMCR power-down) when WoL
+is not enabled. __stmmac_open() then performs the DMA software reset in
+stmmac_hw_setup() before phylink_start() resumes the PHY again.
+
+IEEE 802.3 22.2.4.1.5 allows a PHY to stop its receive clock while
+powered down, and stmmac requires a running receive clock for the DMA
+software reset to complete (the phylink config sets mac_requires_rxc).
+On such setups, e.g. the RK3566-based Home Assistant Green with an
+RTL8211F-VD PHY in RGMII mode, any runtime MTU change now times out and
+leaves the interface dead:
+
+  rk_gmac-dwmac fe010000.ethernet end0: Failed to reset the dma
+  rk_gmac-dwmac fe010000.ethernet end0: stmmac_hw_setup: DMA engine initialization failed
+  rk_gmac-dwmac fe010000.ethernet end0: __stmmac_open: Hw setup failed
+  rk_gmac-dwmac fe010000.ethernet end0: failed reopening the interface after MTU change
+
+In the field this is triggered by NetworkManager applying an MTU while
+activating the connection, breaking networking entirely. The same
+regression has also been reported on i.MX8MP and reproduced on SoCFPGA
+based systems.
+
+Resume the PHY in __stmmac_open() before the hardware setup, making it
+the counterpart of the phylink_stop() in __stmmac_release(), like
+stmmac_resume() already does for the same reason. phylink_start() also
+resumes the PHY, but only after stmmac_hw_setup(), and it cannot be
+moved before the hardware setup since it may bring the link up
+immediately from a workqueue, racing with the initialization (see the
+comment in stmmac_resume()). For the regular ndo_open path the PHY has
+just been attached and is not suspended, in which case
+phylink_prepare_resume() does nothing.
+
+Fixes: db299a0c09e9 ("net: stmmac: move PHY handling out of __stmmac_open()/release()")
+Link: https://github.com/home-assistant/operating-system/issues/4858
+Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Signed-off-by: Stefan Agner <stefan@agner.ch>
+Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260803095156.132827-1-stefan@agner.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index bca81ed28e073..bf2fa56b861be 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -3893,6 +3893,15 @@ static int __stmmac_open(struct net_device *dev,
+                       dma_conf->tx_queue[i].tbs = priv->dma_conf.tx_queue[i].tbs;
+       memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf));
++      /* The PHY is suspended when the interface is reopened without
++       * disconnecting the PHY, e.g. on MTU change. IEEE 802.3 allows PHYs
++       * to stop their receive clock while powered down, but the DMA
++       * software reset in stmmac_hw_setup() requires a running receive
++       * clock, and phylink_start() below resumes the PHY only after the
++       * hardware setup. Resume a suspended PHY here first.
++       */
++      phylink_prepare_resume(priv->phylink);
++
+       stmmac_reset_queues_param(priv);
+       if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) &&
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch b/queue-6.18/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
new file mode 100644 (file)
index 0000000..834c206
--- /dev/null
@@ -0,0 +1,117 @@
+From 080b6c6c90917a15935d807d1a70a1f58a762a6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:38:50 +0000
+Subject: net: thunderbolt: Tear down DMA paths before stopping the rings
+
+From: Fan XinRan <shinjiangjiang@gmail.com>
+
+[ Upstream commit 68bf02b6b4ad3f748c6db71fd77b6c0402d252f4 ]
+
+tbnet_tear_down() stops both rings and frees their frame buffers before
+calling tb_xdomain_disable_paths().  tb_ring_stop() zeroes the ring's
+descriptor base and tbnet_free_buffers() unmaps and frees the pages the
+frames sit in, so by the time __tb_path_deactivate_hop() polls the hop's
+'pending' bit, anything still in flight has nowhere to drain to.
+
+The teardown sequence has been in this order since the driver was added.
+The setup path has not: commit ff7cd07f3064 ("net: thunderbolt: Enable
+DMA paths only after rings are enabled") moved the path enable to the end
+of tbnet_connected_work() and documented why:
+
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
+        */
+
+Teardown was never updated to match, so the rings and the paths now come
+down in the same order they go up instead of in reverse.
+
+On an ASMedia ASM4242 host router the 'pending' bit then never clears:
+every teardown burns the full 500 ms timeout and
+__tb_path_deactivate_hop() returns -ETIMEDOUT.  Raising the timeout to
+5 s does not help, so the hop is not slow to drain, it never drains
+at all.
+
+The failure is invisible above the thunderbolt core.
+__tb_path_deactivate_hops() is void and only calls tb_port_warn();
+tb_path_deactivate(), tb_tunnel_deactivate() and
+__tb_disconnect_xdomain_paths() are void as well, and
+tb_disconnect_xdomain_paths() ends in an unconditional "return 0".  So
+tb_xdomain_disable_paths() reports success and the netdev_warn() below
+it never fires.  Repeated teardowns eventually take the XDomain control
+channel down, after which the peer node is gone and only a power cycle
+brings the controller back.
+
+Deactivating the paths first fixes it.  Measured with kretprobes on a
+stock v6.17 tree with no other patches applied, on a link that was up
+and had just carried traffic:
+
+  before: __tb_path_deactivate_hop() returns 0 for the first hop, then
+          -ETIMEDOUT for the second 500335 us later
+  after:  0 for both, 525 us apart
+
+Alternating the two orderings ABBA over three load levels, four
+teardowns per arm: every teardown failed before the change (21 of 21
+that ran), none failed after (0 of 24).  The before arms ran short
+because the link died partway through.  The same split shows up when
+the interface is enslaved to a bond instead of just brought down, which
+is how I ran into this in the first place.  Throughput and latency after
+the change are unchanged.
+
+Hosts whose routers drain the hop despite the stale descriptor base see
+no functional difference, since the paths end up deactivated either way.
+
+Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
+Signed-off-by: Fan XinRan <shinjiangjiang@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260803-b4-tbnet-teardown-v2-1-27de6a13ca2d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 960839a651e51..ceaba08cd378a 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -389,11 +389,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+                               break;
+               }
+-              tb_ring_stop(net->rx_ring.ring);
+-              tb_ring_stop(net->tx_ring.ring);
+-              tbnet_free_buffers(&net->rx_ring);
+-              tbnet_free_buffers(&net->tx_ring);
+-
++              /* Tear the paths down before stopping the rings.  This mirrors
++               * tbnet_connected_work(), which enables the paths last so the
++               * Rx ring is primed before packets can arrive.  Stopping a
++               * ring zeroes its descriptor base and tbnet_free_buffers()
++               * unmaps and frees the frame buffers, leaving anything still
++               * in flight with nowhere to drain to;
++               * __tb_path_deactivate_hop() then waits for the hop's
++               * 'pending' bit, which on some host routers never clears in
++               * that state.
++               */
+               ret = tb_xdomain_disable_paths(net->xd,
+                                              net->local_transmit_path,
+                                              net->tx_ring.ring->hop,
+@@ -402,6 +407,11 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+               if (ret)
+                       netdev_warn(net->dev, "failed to disable DMA paths\n");
++              tb_ring_stop(net->rx_ring.ring);
++              tb_ring_stop(net->tx_ring.ring);
++              tbnet_free_buffers(&net->rx_ring);
++              tbnet_free_buffers(&net->tx_ring);
++
+               tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+               net->remote_transmit_path = 0;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-flowtable-consolidate-xmit-path.patch b/queue-6.18/netfilter-flowtable-consolidate-xmit-path.patch
new file mode 100644 (file)
index 0000000..d2ecf5a
--- /dev/null
@@ -0,0 +1,238 @@
+From 49a7a1d02e725ae2483dbb5b44c9741fa6d50a61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Oct 2025 12:32:35 +0200
+Subject: netfilter: flowtable: consolidate xmit path
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit b5964aac51e0c286a50e68225e0dfcf11fb554cb ]
+
+Use dev_queue_xmit() for the XMIT_NEIGH case. Store the interface index
+of the real device behind the vlan/pppoe device, this introduces  an
+extra lookup for the real device in the xmit path because rt->dst.dev
+provides the vlan/pppoe device.
+
+XMIT_NEIGH now looks more similar to XMIT_DIRECT but the check for stale
+dst and the neighbour lookup still remain in place which is convenient
+to deal with network topology changes.
+
+Note that nft_flow_route() needs to relax the check for _XMIT_NEIGH so
+the existing basic xfrm offload (which only works in one direction) does
+not break.
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Stable-dep-of: 8aecf0bbcc72 ("netfilter: nf_flow_table: drop existing skb dst before skb_dst_set_noref()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_flow_table.h |  1 +
+ net/netfilter/nf_flow_table_core.c    |  1 +
+ net/netfilter/nf_flow_table_ip.c      | 87 ++++++++++++++++-----------
+ net/netfilter/nf_flow_table_path.c    |  7 +--
+ 4 files changed, 57 insertions(+), 39 deletions(-)
+
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index e9f72d2558e90..7c330caae52bf 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -141,6 +141,7 @@ struct flow_offload_tuple {
+       union {
+               struct {
+                       struct dst_entry *dst_cache;
++                      u32             ifidx;
+                       u32             dst_cookie;
+               };
+               struct {
+diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
+index d3104816b7f71..595a0f19d15e7 100644
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -132,6 +132,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
+               break;
+       case FLOW_OFFLOAD_XMIT_XFRM:
+       case FLOW_OFFLOAD_XMIT_NEIGH:
++              flow_tuple->ifidx = route->tuple[dir].out.ifindex;
+               flow_tuple->dst_cache = dst;
+               flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);
+               break;
+diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
+index 8cd4cf7ae2112..eb4f6a11e779f 100644
+--- a/net/netfilter/nf_flow_table_ip.c
++++ b/net/netfilter/nf_flow_table_ip.c
+@@ -333,19 +333,18 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
+       }
+ }
++struct nf_flow_xmit {
++      const void              *dest;
++      const void              *source;
++      struct net_device       *outdev;
++};
++
+ static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
+-                                     const struct flow_offload_tuple_rhash *tuplehash,
+-                                     unsigned short type)
++                                     struct nf_flow_xmit *xmit)
+ {
+-      struct net_device *outdev;
+-
+-      outdev = dev_get_by_index_rcu(net, tuplehash->tuple.out.ifidx);
+-      if (!outdev)
+-              return NF_DROP;
+-
+-      skb->dev = outdev;
+-      dev_hard_header(skb, skb->dev, type, tuplehash->tuple.out.h_dest,
+-                      tuplehash->tuple.out.h_source, skb->len);
++      skb->dev = xmit->outdev;
++      dev_hard_header(skb, skb->dev, ntohs(skb->protocol),
++                      xmit->dest, xmit->source, skb->len);
+       dev_queue_xmit(skb);
+       return NF_STOLEN;
+@@ -424,10 +423,10 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
+       struct nf_flowtable_ctx ctx = {
+               .in     = state->in,
+       };
++      struct nf_flow_xmit xmit = {};
+       struct flow_offload *flow;
+-      struct net_device *outdev;
++      struct neighbour *neigh;
+       struct rtable *rt;
+-      __be32 nexthop;
+       int ret;
+       tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
+@@ -454,25 +453,34 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
+       switch (tuplehash->tuple.xmit_type) {
+       case FLOW_OFFLOAD_XMIT_NEIGH:
+               rt = dst_rtable(tuplehash->tuple.dst_cache);
+-              outdev = rt->dst.dev;
+-              skb->dev = outdev;
+-              nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
++              xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
++              if (!xmit.outdev) {
++                      flow_offload_teardown(flow);
++                      return NF_DROP;
++              }
++              neigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr));
++              if (IS_ERR(neigh)) {
++                      flow_offload_teardown(flow);
++                      return NF_DROP;
++              }
++              xmit.dest = neigh->ha;
+               skb_dst_set_noref(skb, &rt->dst);
+-              neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb);
+-              ret = NF_STOLEN;
+               break;
+       case FLOW_OFFLOAD_XMIT_DIRECT:
+-              ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IP);
+-              if (ret == NF_DROP)
++              xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
++              if (!xmit.outdev) {
+                       flow_offload_teardown(flow);
++                      return NF_DROP;
++              }
++              xmit.dest = tuplehash->tuple.out.h_dest;
++              xmit.source = tuplehash->tuple.out.h_source;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+-              ret = NF_DROP;
+-              break;
++              return NF_DROP;
+       }
+-      return ret;
++      return nf_flow_queue_xmit(state->net, skb, &xmit);
+ }
+ EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
+@@ -719,9 +727,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+       struct nf_flowtable_ctx ctx = {
+               .in     = state->in,
+       };
+-      const struct in6_addr *nexthop;
++      struct nf_flow_xmit xmit = {};
+       struct flow_offload *flow;
+-      struct net_device *outdev;
++      struct neighbour *neigh;
+       struct rt6_info *rt;
+       int ret;
+@@ -749,24 +757,33 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+       switch (tuplehash->tuple.xmit_type) {
+       case FLOW_OFFLOAD_XMIT_NEIGH:
+               rt = dst_rt6_info(tuplehash->tuple.dst_cache);
+-              outdev = rt->dst.dev;
+-              skb->dev = outdev;
+-              nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
++              xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
++              if (!xmit.outdev) {
++                      flow_offload_teardown(flow);
++                      return NF_DROP;
++              }
++              neigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6));
++              if (IS_ERR(neigh)) {
++                      flow_offload_teardown(flow);
++                      return NF_DROP;
++              }
++              xmit.dest = neigh->ha;
+               skb_dst_set_noref(skb, &rt->dst);
+-              neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb);
+-              ret = NF_STOLEN;
+               break;
+       case FLOW_OFFLOAD_XMIT_DIRECT:
+-              ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IPV6);
+-              if (ret == NF_DROP)
++              xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
++              if (!xmit.outdev) {
+                       flow_offload_teardown(flow);
++                      return NF_DROP;
++              }
++              xmit.dest = tuplehash->tuple.out.h_dest;
++              xmit.source = tuplehash->tuple.out.h_source;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+-              ret = NF_DROP;
+-              break;
++              return NF_DROP;
+       }
+-      return ret;
++      return nf_flow_queue_xmit(state->net, skb, &xmit);
+ }
+ EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
+diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
+index 76d4ff1454398..da56fda2c2b39 100644
+--- a/net/netfilter/nf_flow_table_path.c
++++ b/net/netfilter/nf_flow_table_path.c
+@@ -213,11 +213,11 @@ static void nft_dev_forward_path(struct nf_flow_route *route,
+       }
+       route->tuple[!dir].in.num_encaps = info.num_encaps;
+       route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
++      route->tuple[dir].out.ifindex = info.outdev->ifindex;
+       if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
+               memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
+               memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN);
+-              route->tuple[dir].out.ifindex = info.outdev->ifindex;
+               route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex;
+               route->tuple[dir].xmit_type = info.xmit_type;
+       }
+@@ -265,11 +265,10 @@ int nft_flow_route(const struct nft_pktinfo *pkt, const struct nf_conn *ct,
+       nft_default_forward_path(route, this_dst, dir);
+       nft_default_forward_path(route, other_dst, !dir);
+-      if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH &&
+-          route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) {
++      if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH)
+               nft_dev_forward_path(route, ct, dir, ft);
++      if (route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH)
+               nft_dev_forward_path(route, ct, !dir, ft);
+-      }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-ipset-switch-ext_size-to-atomic64_t.patch b/queue-6.18/netfilter-ipset-switch-ext_size-to-atomic64_t.patch
new file mode 100644 (file)
index 0000000..6216466
--- /dev/null
@@ -0,0 +1,134 @@
+From 1703eae1a67c3333688298d7f719689ee4bb5615 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 20:38:50 +0200
+Subject: netfilter: ipset: switch ext_size to atomic64_t
+
+From: Jozsef Kadlecsik <kadlec@netfilter.org>
+
+[ Upstream commit 712a6f545c359b427daa9a5a782e30d2f8331e25 ]
+
+The hash types do not acquire set->lock, they use 'region locking' where
+only part of the hash table is locked. Parallel inserts and deletes are
+possible and CPUs can race on ->ext_size update.  Switch to atomic64_t.
+
+This leaves another bug unresolved: there still can be a race on
+comment extension re-init.  This will be handled in a later commit
+when converting to rhashtable backend.
+
+Fixes: f66ee0410b1c ("netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports")
+Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netfilter/ipset/ip_set.h  | 2 +-
+ net/netfilter/ipset/ip_set_bitmap_gen.h | 4 ++--
+ net/netfilter/ipset/ip_set_core.c       | 6 +++---
+ net/netfilter/ipset/ip_set_hash_gen.h   | 2 +-
+ net/netfilter/ipset/ip_set_list_set.c   | 4 ++--
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
+index b98331572ad29..cadae9b2578f1 100644
+--- a/include/linux/netfilter/ipset/ip_set.h
++++ b/include/linux/netfilter/ipset/ip_set.h
+@@ -273,7 +273,7 @@ struct ip_set {
+       /* Number of elements (vs timeout) */
+       u32 elements;
+       /* Size of the dynamic extensions (vs timeout) */
+-      size_t ext_size;
++      atomic64_t ext_size;
+       /* Element data size */
+       size_t dsize;
+       /* Offsets to extensions in elements */
+diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
+index 798c7993635e6..d99e2e2e58559 100644
+--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
++++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
+@@ -77,7 +77,7 @@ mtype_flush(struct ip_set *set)
+               mtype_ext_cleanup(set);
+       bitmap_zero(map->members, map->elements);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ /* Calculate the actual memory size of the set data */
+@@ -93,7 +93,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct mtype *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = mtype_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index f51a1af31513c..29bf5ee74fe36 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -350,7 +350,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       size_t len = ext->comment ? strlen(ext->comment) : 0;
+       if (unlikely(c)) {
+-              set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++              atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+               rcu_assign_pointer(comment->c, NULL);
+               kfree_rcu(c, rcu);
+       }
+@@ -362,7 +362,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       if (unlikely(!c))
+               return;
+       strscpy(c->str, ext->comment, len + 1);
+-      set->ext_size += sizeof(*c) + strlen(c->str) + 1;
++      atomic64_add(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, c);
+ }
+ EXPORT_SYMBOL_GPL(ip_set_init_comment);
+@@ -392,7 +392,7 @@ ip_set_comment_free(struct ip_set *set, void *ptr)
+       c = rcu_dereference_protected(comment->c, 1);
+       if (unlikely(!c))
+               return;
+-      set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++      atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, NULL);
+       kfree_rcu(c, rcu);
+ }
+diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
+index 4c1082e38e3d1..81d7f601ed06a 100644
+--- a/net/netfilter/ipset/ip_set_hash_gen.h
++++ b/net/netfilter/ipset/ip_set_hash_gen.h
+@@ -1289,7 +1289,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+-      memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
++      memsize = mtype_ahash_memsize(h, t) + ext_size + atomic64_read(&set->ext_size);
+       htable_bits = t->htable_bits;
+       rcu_read_unlock_bh();
+diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
+index 34bb84d7b174c..7bb807b3c6282 100644
+--- a/net/netfilter/ipset/ip_set_list_set.c
++++ b/net/netfilter/ipset/ip_set_list_set.c
+@@ -421,7 +421,7 @@ list_set_flush(struct ip_set *set)
+       list_for_each_entry_safe(e, n, &map->members, list)
+               list_set_del(set, e);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ static void
+@@ -455,7 +455,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct list_set *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = list_set_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = list_set_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-nf_flow_table-drop-existing-skb-dst-before.patch b/queue-6.18/netfilter-nf_flow_table-drop-existing-skb-dst-before.patch
new file mode 100644 (file)
index 0000000..293a231
--- /dev/null
@@ -0,0 +1,69 @@
+From dd838483a282d1c937c2b629851cef55c798ad6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 09:33:28 +0000
+Subject: netfilter: nf_flow_table: drop existing skb dst before
+ skb_dst_set_noref()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 8aecf0bbcc72605592134c917c222207d8f63ab0 ]
+
+Incoming skbs passing through netfilter flowtable offload hooks (or XFRM
+offload path) might already carry a ref-counted dst_entry assigned during
+earlier RX or routing steps.
+
+Calling skb_dst_set_noref() when skb already holds a ref-counted dst
+overwrites skb->_skb_refdst, leaking the previous dst_entry reference
+count and triggering a DEBUG_NET_WARN_ON_ONCE assertion in
+skb_dst_check_unset():
+
+  WARNING: at skb_dst_check_unset include/linux/skbuff.h:1170
+  WARNING: at skb_dst_set_noref include/linux/skbuff.h:1234
+  WARNING: at nf_flow_offload_ip_hook+0xf6c/0x2b60 net/netfilter/nf_flow_table_ip.c:864
+
+Drop any existing dst_entry reference with skb_dst_drop(skb) before
+setting the non-referenced flowtable destination.
+
+Fixes: 2a79fd3908ac ("netfilter: nf_flow_table: attach dst to skbs")
+Reported-by: syzbot+76d4e3a055aec3b007ec@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a71b141.9511d2ce.1fc5b9.033b.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Link: https://patch.msgid.link/20260804093328.1831847-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_flow_table_ip.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
+index eb4f6a11e779f..4dcc30e7f9e5e 100644
+--- a/net/netfilter/nf_flow_table_ip.c
++++ b/net/netfilter/nf_flow_table_ip.c
+@@ -272,6 +272,7 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+                                     struct dst_entry *dst)
+ {
+       skb_orphan(skb);
++      skb_dst_drop(skb);
+       skb_dst_set_noref(skb, dst);
+       dst_output(state->net, state->sk, skb);
+       return NF_STOLEN;
+@@ -464,6 +465,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
+                       return NF_DROP;
+               }
+               xmit.dest = neigh->ha;
++              skb_dst_drop(skb);
+               skb_dst_set_noref(skb, &rt->dst);
+               break;
+       case FLOW_OFFLOAD_XMIT_DIRECT:
+@@ -768,6 +770,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+                       return NF_DROP;
+               }
+               xmit.dest = neigh->ha;
++              skb_dst_drop(skb);
+               skb_dst_set_noref(skb, &rt->dst);
+               break;
+       case FLOW_OFFLOAD_XMIT_DIRECT:
+-- 
+2.53.0
+
diff --git a/queue-6.18/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-6.18/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..84d2ffd
--- /dev/null
@@ -0,0 +1,50 @@
+From f4e6e5895b5ddc83aac2cc77db7ca6a121aeaec9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 403f7f8dfea2b..66b8da741a06f 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10634,6 +10634,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10675,6 +10676,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-add-missing-rtnl_link_ops-get_size-callback.patch b/queue-6.18/ovpn-add-missing-rtnl_link_ops-get_size-callback.patch
new file mode 100644 (file)
index 0000000..9fe43ca
--- /dev/null
@@ -0,0 +1,56 @@
+From 622571253e3085f96653236b4deda54a6021afa3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:41:30 +0200
+Subject: ovpn: add missing rtnl_link_ops->get_size callback
+
+From: Ralf Lici <ralf@mandelbit.com>
+
+[ Upstream commit 6e9f539e4f01153651dd77609b5ccadd44b74df8 ]
+
+ovpn_fill_info emits IFLA_OVPN_MODE inside IFLA_INFO_DATA, but
+ovpn_link_ops does not provide a get_size callback. Consequently,
+rtnetlink's size estimate for ovpn link messages does not include the
+nested mode attribute.
+
+Available skb tailroom may hide this mismatch. When the remaining space
+is insufficient, however, ovpn_fill_info returns -EMSGSIZE and message
+construction fails.
+
+Add the callback and account for IFLA_OVPN_MODE.
+
+Fixes: c2d950c4672a ("ovpn: add basic interface creation/destruction/management routines")
+Signed-off-by: Ralf Lici <ralf@mandelbit.com>
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/main.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c
+index 3f76b1b0e5f60..47859e1e3ef12 100644
+--- a/drivers/net/ovpn/main.c
++++ b/drivers/net/ovpn/main.c
+@@ -210,6 +210,12 @@ static int ovpn_newlink(struct net_device *dev,
+       return register_netdevice(dev);
+ }
++static size_t ovpn_get_size(const struct net_device *dev)
++{
++      /* IFLA_OVPN_MODE */
++      return nla_total_size(sizeof(u8));
++}
++
+ static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev)
+ {
+       struct ovpn_priv *ovpn = netdev_priv(dev);
+@@ -228,6 +234,7 @@ static struct rtnl_link_ops ovpn_link_ops = {
+       .policy = ovpn_policy,
+       .maxtype = IFLA_OVPN_MAX,
+       .newlink = ovpn_newlink,
++      .get_size = ovpn_get_size,
+       .fill_info = ovpn_fill_info,
+ };
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-disable-ipv4-redirects-on-mp-interfaces.patch b/queue-6.18/ovpn-disable-ipv4-redirects-on-mp-interfaces.patch
new file mode 100644 (file)
index 0000000..94ea64b
--- /dev/null
@@ -0,0 +1,130 @@
+From 40440ca620174039934fd3f69fe7a114c3dd1eb5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:53 +0200
+Subject: ovpn: disable IPv4 redirects on MP interfaces
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 0301aa324941698bec3dd455df1c5abc7afb10db ]
+
+ovpn_mp_alloc() tried to disable SEND_REDIRECTS on a multipeer
+interface, but it runs from ovpn_net_init() (->ndo_init), which
+register_netdevice() invokes before the NETDEV_REGISTER notifier
+chain. The IPv4 in_device is only created when that notifier reaches
+inetdev_event() -> inetdev_init(), so __in_dev_get_rtnl() always
+returned NULL at ndo_init time and the whole redirect-disabling block
+(both the per-device and the per-netns IPV4_DEVCONF_ALL write) was
+dead. MP interfaces therefore kept emitting ICMP redirects.
+
+Disabling redirects only once is not enough either: the IPv4
+in_device is destroyed and recreated when the interface is moved to a
+different network namespace (NETDEV_UNREGISTER/NETDEV_REGISTER), and
+the newly created in_device inherits the destination namespace
+defaults, silently re-enabling SEND_REDIRECTS.
+
+Disable redirects from ovpn_net_open() (->ndo_open) instead: it runs
+every time the interface is brought up, including after the in_device
+has been recreated, so the setting is always re-applied. This mirrors
+what wireguard does in wg_open(). RTNL is held on the ndo_open() path,
+so __in_dev_get_rtnl() is safe.
+
+Fixes: 05003b408c20 ("ovpn: implement multi-peer support")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/main.c | 50 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 35 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c
+index 47859e1e3ef12..a3c15fc301d0d 100644
+--- a/drivers/net/ovpn/main.c
++++ b/drivers/net/ovpn/main.c
+@@ -35,25 +35,11 @@ static void ovpn_priv_free(struct net_device *net)
+ static int ovpn_mp_alloc(struct ovpn_priv *ovpn)
+ {
+-      struct in_device *dev_v4;
+       int i;
+       if (ovpn->mode != OVPN_MODE_MP)
+               return 0;
+-      dev_v4 = __in_dev_get_rtnl(ovpn->dev);
+-      if (dev_v4) {
+-              /* disable redirects as Linux gets confused by ovpn
+-               * handling same-LAN routing.
+-               * This happens because a multipeer interface is used as
+-               * relay point between hosts in the same subnet, while
+-               * in a classic LAN this would not be needed because the
+-               * two hosts would be able to talk directly.
+-               */
+-              IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false);
+-              IPV4_DEVCONF_ALL(dev_net(ovpn->dev), SEND_REDIRECTS) = false;
+-      }
+-
+       /* the peer container is fairly large, therefore we allocate it only in
+        * MP mode
+        */
+@@ -97,9 +83,38 @@ static void ovpn_net_uninit(struct net_device *dev)
+       gro_cells_destroy(&ovpn->gro_cells);
+ }
++static int ovpn_net_open(struct net_device *dev)
++{
++      struct ovpn_priv *ovpn = netdev_priv(dev);
++      struct in_device *dev_v4;
++
++      /* the IPv4 in_device (and thus its config) is recreated whenever the
++       * interface is moved to a new netns, so redirects must be disabled on
++       * every bring-up rather than once at creation time, otherwise the
++       * setting is silently lost after such a move
++       */
++      if (ovpn->mode == OVPN_MODE_MP) {
++              dev_v4 = __in_dev_get_rtnl(dev);
++              if (dev_v4) {
++                      /* disable redirects as Linux gets confused by ovpn
++                       * handling same-LAN routing.
++                       * This happens because a multipeer interface is used as
++                       * relay point between hosts in the same subnet, while
++                       * in a classic LAN this would not be needed because the
++                       * two hosts would be able to talk directly.
++                       */
++                      IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false);
++                      IPV4_DEVCONF_ALL(dev_net(dev), SEND_REDIRECTS) = false;
++              }
++      }
++
++      return 0;
++}
++
+ static const struct net_device_ops ovpn_netdev_ops = {
+       .ndo_init               = ovpn_net_init,
+       .ndo_uninit             = ovpn_net_uninit,
++      .ndo_open               = ovpn_net_open,
+       .ndo_start_xmit         = ovpn_net_xmit,
+ };
+@@ -183,6 +198,7 @@ static int ovpn_newlink(struct net_device *dev,
+       struct ovpn_priv *ovpn = netdev_priv(dev);
+       struct nlattr **data = params->data;
+       enum ovpn_mode mode = OVPN_MODE_P2P;
++      int ret;
+       if (data && data[IFLA_OVPN_MODE]) {
+               mode = nla_get_u8(data[IFLA_OVPN_MODE]);
+@@ -207,7 +223,11 @@ static int ovpn_newlink(struct net_device *dev,
+       else
+               netif_carrier_off(dev);
+-      return register_netdevice(dev);
++      ret = register_netdevice(dev);
++      if (ret < 0)
++              return ret;
++
++      return 0;
+ }
+ static size_t ovpn_get_size(const struct net_device *dev)
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch b/queue-6.18/ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch
new file mode 100644 (file)
index 0000000..1b07c94
--- /dev/null
@@ -0,0 +1,47 @@
+From 55a8eeb38f781ff5af3f719d22ba85bbde7c319a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:50 +0200
+Subject: ovpn: ensure socket is owned by ovpn before deref sk_user_data
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 59aed1eb60d70678a53acccb0cb337a26ce6680e ]
+
+Some subsystems, like BPF SOCKMAP, set sk_user_data without
+actually setting the encap_type.
+
+For this reason, we must make sure that the type is the
+one ovpn expects before dereferencing sk_user_data.
+
+Failing to do so may lead to out-of-bounds reads.
+
+Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/socket.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/net/ovpn/socket.c b/drivers/net/ovpn/socket.c
+index 448cee3b3f9fa..e40e320a6abf5 100644
+--- a/drivers/net/ovpn/socket.c
++++ b/drivers/net/ovpn/socket.c
+@@ -162,6 +162,15 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer)
+               rcu_read_lock();
+               ovpn_sock = rcu_dereference_sk_user_data(sk);
+               if (ovpn_sock) {
++                      /* something else filled the sk_user_data without
++                       * setting the encap_type. Reject the socket.
++                       */
++                      if (!type) {
++                              ovpn_sock = ERR_PTR(-EBUSY);
++                              rcu_read_unlock();
++                              goto sock_release;
++                      }
++
+                       /* socket owned by another ovpn instance, we can't use it */
+                       if (ovpn_sock->ovpn != peer->ovpn) {
+                               ovpn_sock = ERR_PTR(-EBUSY);
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-ensure-tcp-vars-are-initialized-first.patch b/queue-6.18/ovpn-ensure-tcp-vars-are-initialized-first.patch
new file mode 100644 (file)
index 0000000..5084979
--- /dev/null
@@ -0,0 +1,52 @@
+From cb8b183eea118ea7e7e5625f3f7d92c351d70752 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:54 +0200
+Subject: ovpn: ensure TCP vars are initialized first
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 4680c0ebd958fc18e53c8b91d80436b236a8fc09 ]
+
+Netlink calls may access TCP global vars (i.e. when attaching
+a TCP socket), therefore we need to make sure the
+latters are initialized beforehand.
+
+For this reason move the global TCP initialization at the top
+of the module init function.
+
+Fixes: 11851cbd60ea ("ovpn: implement TCP transport")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/main.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c
+index a3c15fc301d0d..0262926449f2e 100644
+--- a/drivers/net/ovpn/main.c
++++ b/drivers/net/ovpn/main.c
+@@ -260,8 +260,11 @@ static struct rtnl_link_ops ovpn_link_ops = {
+ static int __init ovpn_init(void)
+ {
+-      int err = rtnl_link_register(&ovpn_link_ops);
++      int err;
++      ovpn_tcp_init();
++
++      err = rtnl_link_register(&ovpn_link_ops);
+       if (err) {
+               pr_err("ovpn: can't register rtnl link ops: %d\n", err);
+               return err;
+@@ -273,8 +276,6 @@ static int __init ovpn_init(void)
+               goto unreg_rtnl;
+       }
+-      ovpn_tcp_init();
+-
+       return 0;
+ unreg_rtnl:
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-fix-incorrect-use-of-rcu_access_pointer.patch b/queue-6.18/ovpn-fix-incorrect-use-of-rcu_access_pointer.patch
new file mode 100644 (file)
index 0000000..08ed6f7
--- /dev/null
@@ -0,0 +1,37 @@
+From 445050eef4ddad043b32be7ca30bcbd1688c505c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 09:49:26 +0800
+Subject: ovpn: fix incorrect use of rcu_access_pointer()
+
+From: Qingfang Deng <qingfang.deng@linux.dev>
+
+[ Upstream commit 26ba17d845193dac4921ae1ab280d28d1938052e ]
+
+rcu_access_pointer() should only be used to test the value of a pointer,
+not to dereference it. As it's in a spin_lock_bh() critical section, use
+rcu_dereference_bh() instead, avoiding an extra rcu_read_lock().
+
+Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object")
+Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index 9b647a327c468..412ef09abd5e7 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -1244,7 +1244,7 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk,
+       }
+       if (sk) {
+-              ovpn_sock = rcu_access_pointer(peer->sock);
++              ovpn_sock = rcu_dereference_bh(peer->sock);
+               if (!ovpn_sock || ovpn_sock->sk != sk) {
+                       spin_unlock_bh(&ovpn->lock);
+                       return;
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-hash-floated-peer-by-transport-identity-only.patch b/queue-6.18/ovpn-hash-floated-peer-by-transport-identity-only.patch
new file mode 100644 (file)
index 0000000..a63ca16
--- /dev/null
@@ -0,0 +1,94 @@
+From 4bacaecf06b752798d5539ab1e7381b58adf4533 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:52 +0200
+Subject: ovpn: hash floated peer by transport identity only
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit b47a52dcd598a50207a33df304acdf45348a690f ]
+
+The by_transp_addr table is keyed on the peer's remote transport
+address, but the float rehash hashed bind->remote directly, while the
+two other sites that touch the table build a clean key first:
+ovpn_peer_add_mp() and the lookup in ovpn_peer_get_by_transp_addr()
+both hash a sockaddr holding only family/address/port.
+
+For a link-local IPv6 peer, bind->remote carries sin6_scope_id (set
+from ipv6_iface_scope_id() when the endpoint is learned), and that
+field is folded into the jhash() over sizeof(struct sockaddr_in6).
+The lookup never sets sin6_scope_id, so after such a peer floats it is
+rehashed into a scope_id-dependent bucket that lookups (scope_id 0)
+never visit, making the peer unreachable through the by_transp_addr
+fallback. ovpn_peer_transp_match() only compares address and port, so
+the hash was keying on a field the match ignores.
+
+sin6_scope_id must stay in bind->remote because the TX path uses it as
+flowi6_oif, so it cannot just be cleared there. Instead build the hash
+key from family/address/port only, exactly like ovpn_peer_add_mp() and
+the lookup, so all three sites agree on the bucket.
+
+Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index 3824ee1c2e40a..9b647a327c468 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -899,7 +899,10 @@ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
+ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
+                                        const struct ovpn_bind *bind)
+ {
++      struct sockaddr_storage sa = {};
+       struct hlist_nulls_head *nhead;
++      struct sockaddr_in6 *sa6;
++      struct sockaddr_in *sa4;
+       size_t salen;
+       lockdep_assert_held(&peer->ovpn->lock);
+@@ -915,12 +918,26 @@ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
+       if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
+               return;
++      /* Build the hash key from the transport identity only
++       * (family/address/port), matching ovpn_peer_add_mp() and the lookup
++       * in ovpn_peer_get_by_transp_addr(). Hashing bind->remote directly
++       * would fold in sin6_scope_id (set on the float path but never by the
++       * lookup), scattering the peer into a bucket lookups cannot reach.
++       */
+       switch (bind->remote.in4.sin_family) {
+       case AF_INET:
+-              salen = sizeof(struct sockaddr_in);
++              sa4 = (struct sockaddr_in *)&sa;
++              sa4->sin_family = AF_INET;
++              sa4->sin_addr.s_addr = bind->remote.in4.sin_addr.s_addr;
++              sa4->sin_port = bind->remote.in4.sin_port;
++              salen = sizeof(*sa4);
+               break;
+       case AF_INET6:
+-              salen = sizeof(struct sockaddr_in6);
++              sa6 = (struct sockaddr_in6 *)&sa;
++              sa6->sin6_family = AF_INET6;
++              sa6->sin6_addr = bind->remote.in6.sin6_addr;
++              sa6->sin6_port = bind->remote.in6.sin6_port;
++              salen = sizeof(*sa6);
+               break;
+       default:
+               return;
+@@ -929,8 +946,8 @@ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
+       /* remove old hashing (no-op if entry is not currently linked) */
+       hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
+       /* re-add with current transport address */
+-      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
+-                                 &bind->remote, salen);
++      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, &sa,
++                                 salen);
+       hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch b/queue-6.18/ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch
new file mode 100644 (file)
index 0000000..185bf10
--- /dev/null
@@ -0,0 +1,215 @@
+From f878351bc1bb8901897a14ba0aa7b2797d92d1ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:48 +0200
+Subject: ovpn: rehash peer in by_transp_addr table on CMD_PEER_SET
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit cc12f7240c8c4dee557749d33237542613992f14 ]
+
+When userspace updates a peer's remote endpoint via OVPN_CMD_PEER_SET,
+ovpn_nl_peer_modify() installs a new ovpn_bind through
+ovpn_peer_reset_sockaddr(), but ovpn_nl_peer_set_doit() only calls
+ovpn_peer_hash_vpn_ip() to refresh the VPN-IP hashtables. The peer is
+left in the bucket of peers->by_transp_addr corresponding to its old
+remote address.
+
+As a consequence, datagrams arriving at the UDP RX path from the newly
+configured remote hash to a different slot and the lockless lookup in
+ovpn_peer_get_by_transp_addr() (called from ovpn_udp_encap_recv()) does
+not find the peer, until either a float event or a peer re-add fixes
+the bucket.
+
+Introduce ovpn_peer_hash_transp_addr() (modeled after
+ovpn_peer_hash_vpn_ip()) and invoke it from ovpn_nl_peer_set_doit()
+whenever the request carried a new remote address. The helper bails
+out in P2P mode and on peers without a bind (TCP), and relies on
+hlist_nulls_del_init_rcu()'s pprev==NULL short-circuit to handle the
+case of an entry not currently linked in the table.
+
+Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/netlink.c |   6 +++
+ drivers/net/ovpn/peer.c    | 105 +++++++++++++++++++++++++------------
+ drivers/net/ovpn/peer.h    |   1 +
+ 3 files changed, 79 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c
+index bdb56ef0c9040..0051166c59c75 100644
+--- a/drivers/net/ovpn/netlink.c
++++ b/drivers/net/ovpn/netlink.c
+@@ -527,6 +527,12 @@ int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info)
+        */
+       if (ret > 0)
+               ovpn_peer_hash_vpn_ip(peer);
++      /* if the remote endpoint was updated, the by_transp_addr hash bucket
++       * also needs to be refreshed, otherwise incoming packets from the new
++       * remote address would fail the lockless lookup
++       */
++      if (attrs[OVPN_A_PEER_REMOTE_IPV4] || attrs[OVPN_A_PEER_REMOTE_IPV6])
++              ovpn_peer_hash_transp_addr(peer);
+       spin_unlock_bh(&ovpn->lock);
+       ovpn_peer_put(peer);
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index 6b7e368f63f3a..f502f9c576f8f 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -185,6 +185,9 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer,
+       &(*__tbl1)[ovpn_get_hash_slot(*__tbl1, _key, _key_len)];\
+ })
++static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
++                                       const struct ovpn_bind *bind);
++
+ /**
+  * ovpn_peer_endpoints_update - update remote or local endpoint for peer
+  * @peer: peer to update the remote endpoint for
+@@ -192,7 +195,6 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer,
+  */
+ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+ {
+-      struct hlist_nulls_head *nhead;
+       struct sockaddr_storage ss;
+       struct sockaddr_in6 *sa6;
+       bool reset_cache = false;
+@@ -289,46 +291,23 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+       spin_unlock_bh(&peer->lock);
+       /* rehashing is required only in MP mode as P2P has one peer
+-       * only and thus there is no hashtable
++       * only and thus there is no hashtable.
++       *
++       * This function may be invoked concurrently, so re-read peer->bind
++       * under the proper locks and rehash against its current value.
+        */
+       if (peer->ovpn->mode != OVPN_MODE_MP)
+               return;
++      /* This function may be invoked concurrently, therefore another
++       * float may have happened in parallel: re-acquire the locks and
++       * rehash using the peer->bind->remote directly as key
++       */
+       spin_lock_bh(&peer->ovpn->lock);
+       spin_lock_bh(&peer->lock);
+       bind = rcu_dereference_protected(peer->bind,
+                                        lockdep_is_held(&peer->lock));
+-      if (unlikely(!bind))
+-              goto unlock2;
+-
+-      /* peer may have been concurrently removed between the caller's
+-       * initial lookup and our acquisition of ovpn->lock; skip the
+-       * rehash so we don't re-insert a removed peer
+-       */
+-      if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
+-              goto unlock2;
+-
+-      /* This function may be invoked concurrently, therefore another
+-       * float may have happened in parallel: perform rehashing
+-       * using the peer->bind->remote directly as key
+-       */
+-
+-      switch (bind->remote.in4.sin_family) {
+-      case AF_INET:
+-              salen = sizeof(*sa);
+-              break;
+-      case AF_INET6:
+-              salen = sizeof(*sa6);
+-              break;
+-      }
+-
+-      /* remove old hashing */
+-      hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
+-      /* re-add with new transport address */
+-      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
+-                                 &bind->remote, salen);
+-      hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
+-unlock2:
++      __ovpn_peer_hash_transp_addr(peer, bind);
+       spin_unlock_bh(&peer->lock);
+       spin_unlock_bh(&peer->ovpn->lock);
+       return;
+@@ -897,6 +876,66 @@ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
+       return match;
+ }
++/* Move @peer to the by_transp_addr bucket matching its current bind.
++ *
++ * Caller must hold both peer->ovpn->lock and peer->lock, and must have
++ * already dereferenced a valid (non-NULL) peer->bind, passed in as @bind.
++ */
++static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
++                                       const struct ovpn_bind *bind)
++{
++      struct hlist_nulls_head *nhead;
++      size_t salen;
++
++      lockdep_assert_held(&peer->ovpn->lock);
++      lockdep_assert_held(&peer->lock);
++
++      if (WARN_ON_ONCE(!bind))
++              return;
++
++      /* peer may have been concurrently removed between the caller's
++       * initial lookup and our acquisition of ovpn->lock; skip the
++       * rehash so we don't re-insert a removed peer
++       */
++      if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
++              return;
++
++      switch (bind->remote.in4.sin_family) {
++      case AF_INET:
++              salen = sizeof(struct sockaddr_in);
++              break;
++      case AF_INET6:
++              salen = sizeof(struct sockaddr_in6);
++              break;
++      default:
++              return;
++      }
++
++      /* remove old hashing (no-op if entry is not currently linked) */
++      hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
++      /* re-add with current transport address */
++      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
++                                 &bind->remote, salen);
++      hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
++}
++
++void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer)
++{
++      struct ovpn_bind *bind;
++
++      lockdep_assert_held(&peer->ovpn->lock);
++
++      /* rehashing makes sense only in multipeer mode */
++      if (peer->ovpn->mode != OVPN_MODE_MP)
++              return;
++
++      spin_lock_bh(&peer->lock);
++      bind = rcu_dereference_protected(peer->bind,
++                                       lockdep_is_held(&peer->lock));
++      __ovpn_peer_hash_transp_addr(peer, bind);
++      spin_unlock_bh(&peer->lock);
++}
++
+ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer)
+ {
+       struct hlist_nulls_head *nhead;
+diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h
+index 4de5aeae33f7d..9a05a278e1cd0 100644
+--- a/drivers/net/ovpn/peer.h
++++ b/drivers/net/ovpn/peer.h
+@@ -148,6 +148,7 @@ struct ovpn_peer *ovpn_peer_get_by_id(struct ovpn_priv *ovpn, u32 peer_id);
+ struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn,
+                                      struct sk_buff *skb);
+ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer);
++void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer);
+ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
+                           struct ovpn_peer *peer);
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch b/queue-6.18/ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch
new file mode 100644 (file)
index 0000000..513290a
--- /dev/null
@@ -0,0 +1,142 @@
+From 0eb6a27c132eb080761d78d1fc3fc3e5f0fc8c30 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:47 +0200
+Subject: ovpn: skip rehash for peers already removed from by_id
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 33ec10567fe14456063daf549fdf1a4f53448e4c ]
+
+ovpn_nl_peer_set_doit() resolves the target peer via
+ovpn_peer_get_by_id() before taking ovpn->lock. In the window between
+the lookup (which only takes a refcount) and the subsequent
+spin_lock_bh(&ovpn->lock), a concurrent OVPN_CMD_PEER_DEL, keepalive
+expiry, or socket teardown can take ovpn->lock first, run
+ovpn_peer_remove() to unhash the peer from all four tables (by_id,
+by_vpn_addr4/6, by_transp_addr) and release the lock. set_doit then
+acquires ovpn->lock and calls ovpn_peer_hash_vpn_ip(), which
+re-inserts the now-removed peer back into the rehashing tables.
+
+The same race affects the float path: ovpn_peer_endpoints_update()
+holds only a refcount and acquires ovpn->lock very late (after async
+AEAD decrypt and a netlink notification), then rehashes the peer
+in the by_transp_addr table.
+
+The resurrected peer becomes reachable again from the RX lookup
+(ovpn_peer_get_by_transp_addr) and the TX VPN-IP lookup, even though
+userspace believes it is gone. Once the data-path refcount drops the
+peer is freed via call_rcu while the hash entries embedded in it
+remain linked, opening a UAF window.
+
+Bail out of the rehash when hash_entry_id is unhashed, mirroring
+the sentinel already used by ovpn_peer_remove() to detect the
+already-removed state. The check is safe under ovpn->lock, which
+serializes every mutation of hash_entry_id, and is a no-op for the
+add path because ovpn_peer_add_mp() inserts hash_entry_id before
+calling ovpn_peer_hash_vpn_ip().
+
+Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 73 ++++++++++++++++++++++++-----------------
+ 1 file changed, 43 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index 85fa9bd475f45..6b7e368f63f3a 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -291,40 +291,46 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+       /* rehashing is required only in MP mode as P2P has one peer
+        * only and thus there is no hashtable
+        */
+-      if (peer->ovpn->mode == OVPN_MODE_MP) {
+-              spin_lock_bh(&peer->ovpn->lock);
+-              spin_lock_bh(&peer->lock);
+-              bind = rcu_dereference_protected(peer->bind,
+-                                               lockdep_is_held(&peer->lock));
+-              if (unlikely(!bind)) {
+-                      spin_unlock_bh(&peer->lock);
+-                      spin_unlock_bh(&peer->ovpn->lock);
+-                      return;
+-              }
++      if (peer->ovpn->mode != OVPN_MODE_MP)
++              return;
+-              /* This function may be invoked concurrently, therefore another
+-               * float may have happened in parallel: perform rehashing
+-               * using the peer->bind->remote directly as key
+-               */
++      spin_lock_bh(&peer->ovpn->lock);
++      spin_lock_bh(&peer->lock);
++      bind = rcu_dereference_protected(peer->bind,
++                                       lockdep_is_held(&peer->lock));
++      if (unlikely(!bind))
++              goto unlock2;
+-              switch (bind->remote.in4.sin_family) {
+-              case AF_INET:
+-                      salen = sizeof(*sa);
+-                      break;
+-              case AF_INET6:
+-                      salen = sizeof(*sa6);
+-                      break;
+-              }
++      /* peer may have been concurrently removed between the caller's
++       * initial lookup and our acquisition of ovpn->lock; skip the
++       * rehash so we don't re-insert a removed peer
++       */
++      if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
++              goto unlock2;
+-              /* remove old hashing */
+-              hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
+-              /* re-add with new transport address */
+-              nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
+-                                         &bind->remote, salen);
+-              hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
+-              spin_unlock_bh(&peer->lock);
+-              spin_unlock_bh(&peer->ovpn->lock);
++      /* This function may be invoked concurrently, therefore another
++       * float may have happened in parallel: perform rehashing
++       * using the peer->bind->remote directly as key
++       */
++
++      switch (bind->remote.in4.sin_family) {
++      case AF_INET:
++              salen = sizeof(*sa);
++              break;
++      case AF_INET6:
++              salen = sizeof(*sa6);
++              break;
+       }
++
++      /* remove old hashing */
++      hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
++      /* re-add with new transport address */
++      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
++                                 &bind->remote, salen);
++      hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
++unlock2:
++      spin_unlock_bh(&peer->lock);
++      spin_unlock_bh(&peer->ovpn->lock);
+       return;
+ unlock:
+       spin_unlock_bh(&peer->lock);
+@@ -901,6 +907,13 @@ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer)
+       if (peer->ovpn->mode != OVPN_MODE_MP)
+               return;
++      /* peer may have been concurrently removed between the caller's
++       * initial lookup and our acquisition of ovpn->lock; skip the
++       * rehash so we don't re-insert a removed peer
++       */
++      if (hlist_unhashed(&peer->hash_entry_id))
++              return;
++
+       if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) {
+               /* remove potential old hashing */
+               hlist_nulls_del_init_rcu(&peer->hash_entry_addr4);
+-- 
+2.53.0
+
diff --git a/queue-6.18/ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch b/queue-6.18/ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch
new file mode 100644 (file)
index 0000000..ac4e70d
--- /dev/null
@@ -0,0 +1,91 @@
+From b86375bc7a97bb870b966e1d260187ea400e9af3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:51 +0200
+Subject: ovpn: zero-initialize sockaddr before learning a floated endpoint
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 3f012bdbabe211ccbc0c50ea5a1dbc60f8af1532 ]
+
+ovpn_peer_endpoints_update() builds the new remote endpoint in an
+on-stack struct sockaddr_storage that is left uninitialized. For IPv4
+only sin_family/sin_addr/sin_port are written, leaving the 8-byte
+sin_zero padding as stack garbage (for IPv6, sin6_flowinfo is left
+uninitialized likewise).
+
+ovpn_peer_reset_sockaddr() -> ovpn_bind_from_sockaddr() then memcpy()s
+sizeof(struct sockaddr_in)/sizeof(struct sockaddr_in6) bytes - padding
+included - into bind->remote. That buffer is later hashed with jhash()
+over the same length to place the peer in the by_transp_addr table, so
+the garbage padding lands the floated peer in an essentially random
+bucket. Lockless lookups in ovpn_peer_get_by_transp_addr() build their
+key from a zero-initialized sockaddr_storage, compute a different bucket
+and fail to find the peer.
+
+This is also a plain use of uninitialized stack memory in jhash().
+
+Build the floated endpoint with a designated initializer so the
+padding (sin_zero for IPv4, sin6_flowinfo for IPv6) is zeroed as part
+of the assignment. This keeps the padding out of the by_transp_addr
+hash key without memset-ing the whole sockaddr_storage on every
+received packet.
+
+Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 31 +++++++++++++++++++++++--------
+ 1 file changed, 23 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index f502f9c576f8f..3824ee1c2e40a 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -218,9 +218,16 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+                        */
+                       local_ip = &ip_hdr(skb)->daddr;
+                       sa = (struct sockaddr_in *)&ss;
+-                      sa->sin_family = AF_INET;
+-                      sa->sin_addr.s_addr = ip_hdr(skb)->saddr;
+-                      sa->sin_port = udp_hdr(skb)->source;
++                      /* use a designated initializer so the sin_zero padding
++                       * is zeroed (it ends up in the by_transp_addr hash key)
++                       * without memset-ing the whole sockaddr_storage on the
++                       * RX fast path
++                       */
++                      *sa = (struct sockaddr_in) {
++                              .sin_family = AF_INET,
++                              .sin_addr.s_addr = ip_hdr(skb)->saddr,
++                              .sin_port = udp_hdr(skb)->source,
++                      };
+                       salen = sizeof(*sa);
+                       reset_cache = true;
+                       break;
+@@ -246,11 +253,19 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+                        */
+                       local_ip = &ipv6_hdr(skb)->daddr;
+                       sa6 = (struct sockaddr_in6 *)&ss;
+-                      sa6->sin6_family = AF_INET6;
+-                      sa6->sin6_addr = ipv6_hdr(skb)->saddr;
+-                      sa6->sin6_port = udp_hdr(skb)->source;
+-                      sa6->sin6_scope_id = ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr,
+-                                                               skb->skb_iif);
++                      /* use a designated initializer so the sin6_flowinfo
++                       * padding is zeroed (it ends up in the by_transp_addr
++                       * hash key) without memset-ing the whole
++                       * sockaddr_storage on the RX fast path
++                       */
++                      *sa6 = (struct sockaddr_in6) {
++                              .sin6_family = AF_INET6,
++                              .sin6_addr = ipv6_hdr(skb)->saddr,
++                              .sin6_port = udp_hdr(skb)->source,
++                              .sin6_scope_id =
++                                      ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr,
++                                                          skb->skb_iif),
++                      };
+                       salen = sizeof(*sa6);
+                       reset_cache = true;
+                       break;
+-- 
+2.53.0
+
diff --git a/queue-6.18/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch b/queue-6.18/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch
new file mode 100644 (file)
index 0000000..21ee2c3
--- /dev/null
@@ -0,0 +1,54 @@
+From 884aa49e157bf14ac7f79502cbf920348b8041ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 17:00:30 +0000
+Subject: pds_core: cancel pending PCI reset work on AER recovery
+
+From: Nikhil P. Rao <nikhil.rao@amd.com>
+
+[ Upstream commit 57d635329d799b79096155cdf47ee0013d6780d1 ]
+
+pdsc_check_pci_health() queues pci_reset_work when it sees a broken PCI
+connection, and nothing cancels it. When the PCI core starts AER
+recovery, pdsc_pci_error_detected() runs pdsc_reset_prepare() and
+recovers the device, but a pci_reset_work queued just before is left
+pending. If it runs after recovery released the device lock, it resets a
+device the driver now considers healthy, bouncing the link for no reason.
+
+Cancel pci_reset_work in pdsc_pci_error_detected() after
+pdsc_reset_prepare(), which has already stopped the health thread so it
+cannot requeue the work. cancel_work_sync() is safe under the device
+lock here because pdsc_pci_reset_thread() uses pci_try_reset_function(),
+which returns instead of blocking on the lock. Only PFs initialize
+pci_reset_work, so guard the cancel with !is_virtfn.
+
+Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread")
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260714180223.1642792-2-nikhil.rao%40amd.com?part=1
+Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260727170030.361116-1-nikhil.rao@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pds_core/main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index dad7fd03287db..61be6def50b1c 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -562,7 +562,11 @@ static pci_ers_result_t pdsc_pci_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t error)
+ {
+       if (error == pci_channel_io_frozen) {
++              struct pdsc *pdsc = pci_get_drvdata(pdev);
++
+               pdsc_reset_prepare(pdev);
++              if (!pdev->is_virtfn)
++                      cancel_work_sync(&pdsc->pci_reset_work);
+               return PCI_ERS_RESULT_NEED_RESET;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/pds_core-keep-the-health-thread-stopped-during-reset.patch b/queue-6.18/pds_core-keep-the-health-thread-stopped-during-reset.patch
new file mode 100644 (file)
index 0000000..c7dd6ae
--- /dev/null
@@ -0,0 +1,87 @@
+From 1db3da527cdd7c78345e3f374a490511bed9a356 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 16:45:48 +0000
+Subject: pds_core: keep the health thread stopped during reset
+
+From: Nikhil P. Rao <nikhil.rao@amd.com>
+
+[ Upstream commit cd09971dcc1c499ae0879010a00e9dba87abdc4f ]
+
+Commit d9407ff11809 ("pds_core: Prevent health thread from running
+during reset/remove") stops the health thread with cancel_work_sync()
+before a reset, but a devcmd timeout during pdsc_fw_down() re-queues
+health_work, so pdsc_health_thread() runs again mid-reset and double
+allocates the core DMA queues via pdsc_fw_up().
+
+Only the reset path is affected: on remove PDSC_S_STOPPING_DRIVER gates
+the health thread and the workqueue is destroyed.
+
+Use disable_work_sync() to cancel health_work and block further
+queue_work() on it, and enable_work() in pdsc_restart_health_thread() to
+re-allow it after the reset.
+
+disable_work_sync() keeps a disable depth, so every disable must be
+matched by one enable. pdsc_reset_prepare() stops the health thread and
+pdsc_reset_done() restarts it. On the AER path pdsc_pci_error_detected()
+calls pdsc_reset_prepare(), then pdsc_pci_error_resume() re-inits via
+pci_reset_function_locked() (pds_core has no .slot_reset handler), which
+runs the pair again - stopping the thread twice but restarting it once.
+Gate the disable and enable on a health_stopped flag so each fires at
+most once per stopped/running transition.
+
+Fixes: d9407ff11809 ("pds_core: Prevent health thread from running during reset/remove")
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2
+Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260727164548.359562-1-nikhil.rao@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pds_core/core.h |  1 +
+ drivers/net/ethernet/amd/pds_core/main.c | 10 ++++++++--
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h
+index 0b53a1fab46d0..e2a86ef581dfc 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.h
++++ b/drivers/net/ethernet/amd/pds_core/core.h
+@@ -171,6 +171,7 @@ struct pdsc {
+       struct timer_list wdtimer;
+       unsigned int wdtimer_period;
+       struct work_struct health_work;
++      bool health_stopped;
+       struct devlink_health_reporter *fw_reporter;
+       u32 fw_recoveries;
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index a4962dba3140b..dad7fd03287db 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -471,8 +471,10 @@ static void pdsc_stop_health_thread(struct pdsc *pdsc)
+               return;
+       timer_shutdown_sync(&pdsc->wdtimer);
+-      if (pdsc->health_work.func)
+-              cancel_work_sync(&pdsc->health_work);
++      if (pdsc->health_work.func && !pdsc->health_stopped) {
++              disable_work_sync(&pdsc->health_work);
++              pdsc->health_stopped = true;
++      }
+ }
+ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+@@ -480,6 +482,10 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+       if (pdsc->pdev->is_virtfn)
+               return;
++      if (pdsc->health_stopped) {
++              enable_work(&pdsc->health_work);
++              pdsc->health_stopped = false;
++      }
+       timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
+       mod_timer(&pdsc->wdtimer, jiffies + 1);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch b/queue-6.18/pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch
new file mode 100644 (file)
index 0000000..e59de02
--- /dev/null
@@ -0,0 +1,65 @@
+From 50f1d566604c4da03cf2f95dbd7abdce9bc428a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jul 2026 15:35:59 +0200
+Subject: pinctrl: qcom: ipq806x: mark gpio as a GPIO pin function
+
+From: Hans Ulli Kroll <linux@ulli-kroll.de>
+
+[ Upstream commit 687f39faccba29ab26de965411db37e849af8ec2 ]
+
+The qcom pinctrl core supports marking functions that represent GPIO mode
+via PINCTRL_GPIO_PINFUNCTION(), so that strict pinmuxing does not reject
+GPIO requests for pins that are muxed to the GPIO function.
+
+Add a IPQ_GPIO_PIN_FUNCTION() helper and use it for the ipq806x gpio
+function, matching how the msm-based qcom drivers handle this.
+
+This allows ipq806x to keep the GPIO-related configuration in DTS
+without tripping over strict pinmux ownership
+checks.
+
+Fixes: cc85cb96e2e4 ("pinctrl: qcom: make the pinmuxing strict")
+Signed-off-by: Hans Ulli Kroll <linux@ulli-kroll.de>
+Acked-by: Linus Walleij <linusw@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260719134548.8830-2-linux@ulli-kroll.de
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/qcom/pinctrl-ipq8064.c | 2 +-
+ drivers/pinctrl/qcom/pinctrl-msm.h     | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+index 0a9e357e64c60..c1651f112950e 100644
+--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c
++++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+@@ -480,7 +480,7 @@ static const char * const ps_hold_groups[] = {
+ };
+ static const struct pinfunction ipq8064_functions[] = {
+-      IPQ_PIN_FUNCTION(gpio),
++      IPQ_GPIO_PIN_FUNCTION(gpio),
+       IPQ_PIN_FUNCTION(mdio),
+       IPQ_PIN_FUNCTION(ssbi),
+       IPQ_PIN_FUNCTION(spmi),
+diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
+index 120217012a9f6..33d8b17f2e559 100644
+--- a/drivers/pinctrl/qcom/pinctrl-msm.h
++++ b/drivers/pinctrl/qcom/pinctrl-msm.h
+@@ -24,6 +24,11 @@ struct pinctrl_pin_desc;
+                                       fname##_groups,         \
+                                       ARRAY_SIZE(fname##_groups))
++#define IPQ_GPIO_PIN_FUNCTION(fname)                                  \
++      [IPQ_MUX_##fname] = PINCTRL_GPIO_PINFUNCTION(#fname,            \
++                                      fname##_groups,         \
++                                      ARRAY_SIZE(fname##_groups))
++
+ #define MSM_PIN_FUNCTION(fname)                               \
+       [msm_mux_##fname] = PINCTRL_PINFUNCTION(#fname,         \
+                                       fname##_groups,         \
+-- 
+2.53.0
+
diff --git a/queue-6.18/pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch b/queue-6.18/pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch
new file mode 100644 (file)
index 0000000..644ce7b
--- /dev/null
@@ -0,0 +1,59 @@
+From eced0e0c1d916d59fe09ecfe4ef2c394ec6d0fdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jul 2026 15:36:00 +0200
+Subject: pinctrl: qcom: ipq806x: mark pci reset as a GPIO pin function
+
+From: Hans Ulli Kroll <linux@ulli-kroll.de>
+
+[ Upstream commit fd46760956509f580f7d3d25db4de10e7c6f949b ]
+
+The qcom pinctrl core supports marking functions that represent GPIO mode
+via PINCTRL_GPIO_PINFUNCTION(), so that strict pinmuxing does not reject
+GPIO requests for pins that are muxed to the GPIO function.
+
+Mark PCIe reset as GPIO pin function
+
+This allows ipq806x to keep the PCIe-reset related configuration in DTS
+without tripping over strict pinmux ownership checks.
+
+Fixes: cc85cb96e2e4 ("pinctrl: qcom: make the pinmuxing strict")
+Signed-off-by: Hans Ulli Kroll <linux@ulli-kroll.de>
+Acked-by: Linus Walleij <linusw@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260719134548.8830-3-linux@ulli-kroll.de
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/qcom/pinctrl-ipq8064.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+index c1651f112950e..f35dbe07ab6fe 100644
+--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c
++++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+@@ -507,19 +507,19 @@ static const struct pinfunction ipq8064_functions[] = {
+       IPQ_PIN_FUNCTION(usb2_hsic),
+       IPQ_PIN_FUNCTION(rgmii2),
+       IPQ_PIN_FUNCTION(sata),
+-      IPQ_PIN_FUNCTION(pcie1_rst),
++      IPQ_GPIO_PIN_FUNCTION(pcie1_rst),
+       IPQ_PIN_FUNCTION(pcie1_prsnt),
+       IPQ_PIN_FUNCTION(pcie1_pwren_n),
+       IPQ_PIN_FUNCTION(pcie1_pwren),
+       IPQ_PIN_FUNCTION(pcie1_pwrflt),
+       IPQ_PIN_FUNCTION(pcie1_clk_req),
+-      IPQ_PIN_FUNCTION(pcie2_rst),
++      IPQ_GPIO_PIN_FUNCTION(pcie2_rst),
+       IPQ_PIN_FUNCTION(pcie2_prsnt),
+       IPQ_PIN_FUNCTION(pcie2_pwren_n),
+       IPQ_PIN_FUNCTION(pcie2_pwren),
+       IPQ_PIN_FUNCTION(pcie2_pwrflt),
+       IPQ_PIN_FUNCTION(pcie2_clk_req),
+-      IPQ_PIN_FUNCTION(pcie3_rst),
++      IPQ_GPIO_PIN_FUNCTION(pcie3_rst),
+       IPQ_PIN_FUNCTION(pcie3_prsnt),
+       IPQ_PIN_FUNCTION(pcie3_pwren_n),
+       IPQ_PIN_FUNCTION(pcie3_pwren),
+-- 
+2.53.0
+
diff --git a/queue-6.18/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch b/queue-6.18/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
new file mode 100644 (file)
index 0000000..e370ec1
--- /dev/null
@@ -0,0 +1,104 @@
+From 66615729bc455a5c238a8a00bc2e94161aced88d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 12:29:48 +0000
+Subject: Revert "net: thunderbolt: Enable end-to-end flow control also in
+ transmit"
+
+From: Fan Ye <fy15309206903@gmail.com>
+
+[ Upstream commit 1881f2efbf7f78dc0a79a387b29fde6ff56d3731 ]
+
+This reverts commit a8065af3346ebd7c76ebc113451fb3ba94cf7769.
+
+Per the USB4 spec, a Transmit Descriptor Ring with E2E flow control
+disabled does not require any credits to be available before the Host
+Interface Adapter Layer transmits a tunneled packet from it. Once E2E is
+enabled on that ring the controller must first obtain end-to-end
+credits.
+
+The ASMedia ASM4242 USB4 host router (PCI 1b21:2425) never delivers
+those credits. The controller does accept the configuration: reading the
+ring OPTIONS register back right after tb_ring_start() returns exactly
+what was written, including RING_FLAG_E2E_FLOW_CONTROL (bit 28) and the
+E2E HopID field. No credit ever arrives though, so the Tx ring's
+hardware consumer index never advances and the link carries no traffic
+at all.
+
+Measured on two hosts connected point to point, onboard ASM4242 on MSI
+X870E and X870, v6.17, stock drivers/net/thunderbolt/main.c with only
+this revert applied on top:
+
+  before: 100% packet loss to the peer; thunderbolt0 is up and the
+          XDomain handshake completes ("new host found"), but iperf3
+          fails with "No route to host" once the neighbour entry
+          expires
+  after:  0% packet loss, 0.28 ms RTT; iperf3 4.21 Gb/s one way and
+          5.17 Gb/s the other (5 runs each, stddev <= 0.02), 1
+          retransmit in 10 s
+
+An instrumented build additionally showed a frozen-Tx-consumer watchdog
+firing ~30k times in a 10 s window before this change.
+
+Rx-side E2E is not touched by this revert, so peers that do return
+credits keep receive-side flow control.
+
+ASMedia does not look like an isolated case. The out-of-tree
+thunderbolt-ibverbs project disables native E2E on AMD NHI by default,
+noting that "Strix Halo has reproduced TX completion wedges with
+multiple native E2E rings active" -- the same failure mode, on a
+different vendor. Since the driver has no way to tell in advance which
+host router returns the credits, going back to the previous behaviour
+looks safer than adding a quirk per affected part; Tx-side E2E can be
+reintroduced as an opt-in for controllers that are known to implement
+the credit return.
+
+Note that the reverted commit was not fixing a reported problem, it was
+derived from the spec wording alone, so this revert is not expected to
+regress a known workload. Cc'ing the original author in case there was
+one.
+
+Fixes: a8065af3346e ("net: thunderbolt: Enable end-to-end flow control also in transmit")
+Cc: zhangjianrong <zhangjianrong5@huawei.com>
+Signed-off-by: Fan Ye <fy15309206903@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260727123002.25225-1-fy15309206903@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 5d7d11d75b0b8..960839a651e51 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -928,12 +928,8 @@ static int tbnet_open(struct net_device *dev)
+       netif_carrier_off(dev);
+-      flags = RING_FLAG_FRAME;
+-      /* Only enable full E2E if the other end supports it too */
+-      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
+-              flags |= RING_FLAG_E2E;
+-
+-      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags);
++      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE,
++                              RING_FLAG_FRAME);
+       if (!ring) {
+               netdev_err(dev, "failed to allocate Tx ring\n");
+               return -ENOMEM;
+@@ -952,6 +948,11 @@ static int tbnet_open(struct net_device *dev)
+       sof_mask = BIT(TBIP_PDF_FRAME_START);
+       eof_mask = BIT(TBIP_PDF_FRAME_END);
++      flags = RING_FLAG_FRAME;
++      /* Only enable full E2E if the other end supports it too */
++      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
++              flags |= RING_FLAG_E2E;
++
+       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags,
+                               net->tx_ring.ring->hop, sof_mask,
+                               eof_mask, tbnet_start_poll, net);
+-- 
+2.53.0
+
diff --git a/queue-6.18/s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch b/queue-6.18/s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch
new file mode 100644 (file)
index 0000000..c03ac0a
--- /dev/null
@@ -0,0 +1,91 @@
+From c700d726caf538a73ac46a4f5177250ce019fa6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 15:10:43 +0200
+Subject: s390/ism: Fix UAF of sba and ieq during ism_dev_exit()
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit b1896543ce59c4258625a35cf41e23a9a1f80ea2 ]
+
+A ism interrupt handler can be active in parallel with ism_dev_exit(),
+accessing freed data structures.
+
+No new interrupts will be generated after unregister_ieq(). Drain ongoing
+interrupt handlers by free_irq(), before freeing ism data structures.
+
+Fixes: 684b89bc39ce ("s390/ism: add device driver for internal shared memory")
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260805131043.954639-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/net/ism_drv.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
+index f84aa2e676e9b..b842410cf41cc 100644
+--- a/drivers/s390/net/ism_drv.c
++++ b/drivers/s390/net/ism_drv.c
+@@ -149,13 +149,16 @@ static int unregister_sba(struct ism_dev *ism)
+       if (ret && ret != ISM_ERROR)
+               return -EIO;
++      return 0;
++}
++
++static void ism_free_sba(struct ism_dev *ism)
++{
+       dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
+                         ism->sba, ism->sba_dma_addr);
+       ism->sba = NULL;
+       ism->sba_dma_addr = 0;
+-
+-      return 0;
+ }
+ static int unregister_ieq(struct ism_dev *ism)
+@@ -169,13 +172,16 @@ static int unregister_ieq(struct ism_dev *ism)
+       if (ret && ret != ISM_ERROR)
+               return -EIO;
++      return 0;
++}
++
++static void ism_free_ieq(struct ism_dev *ism)
++{
+       dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
+                         ism->ieq, ism->ieq_dma_addr);
+       ism->ieq = NULL;
+       ism->ieq_dma_addr = 0;
+-
+-      return 0;
+ }
+ static int ism_read_local_gid(struct dibs_dev *dibs)
+@@ -574,6 +580,7 @@ static int ism_dev_init(struct ism_dev *ism)
+ unreg_sba:
+       unregister_sba(ism);
++      ism_free_sba(ism);
+ free_irq:
+       free_irq(pci_irq_vector(pdev, 0), ism);
+ free_vectors:
+@@ -586,9 +593,13 @@ static void ism_dev_exit(struct ism_dev *ism)
+ {
+       struct pci_dev *pdev = ism->pdev;
++      /* ism will only generate new IRQs while ieq & sba are registered */
+       unregister_ieq(ism);
+       unregister_sba(ism);
++      /* drain ongoing irpt handlers */
+       free_irq(pci_irq_vector(pdev, 0), ism);
++      ism_free_ieq(ism);
++      ism_free_sba(ism);
+       pci_free_irq_vectors(pdev);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-6.18/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..7c51079
--- /dev/null
@@ -0,0 +1,54 @@
+From 00537ea419ca796773b9ca4883ed23d9e095f27b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index e560f7ee4adb3..9fff11115b417 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -573,6 +573,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-6.18/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-6.18/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..132801f
--- /dev/null
@@ -0,0 +1,57 @@
+From a676a8861312848d181a8f11f169642523a26535 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 721e147091a97..757aff3e917dc 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3336,12 +3336,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-6.18/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch b/queue-6.18/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
new file mode 100644 (file)
index 0000000..21b4130
--- /dev/null
@@ -0,0 +1,88 @@
+From 277b423d991c08381f4f213fdda7662f33e38c16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 21:46:35 +0200
+Subject: selftests/ftrace: refactor eprobes test to fix argument checks
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+[ Upstream commit 6e3abef2a27e7402a94111c9eff85d887e64a309 ]
+
+The add/remove eprobe test installs an eprobe for the openat syscall and
+runs ls. It checks the filenames that were opened by ls against a
+whitelist and a blacklist.
+
+Commit 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING
+pointer") fixed access to some string fields in eprobes. This triggers
+test failures as the blacklist does not allow relative paths for the
+openat parameters.
+
+What makes this test unstable is the fact that the openat calls vary a
+lot between different systems.
+
+Refactor the test to make it more robust. "cd <directory>" will issue a
+chdir syscall with the target directory as parameter. Set an eprobe on
+the sys_enter_chdir event and filter for the exact directory name. Allow
+(fault) as fallback.
+
+Link: https://lore.kernel.org/all/20260804194705.760893-1-martin@kaiser.cx/
+
+Fixes: 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING pointer")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202607151010.b68428e1-lkp@intel.com
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc  | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index c300eb0202620..e2322693d0c32 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,16 +1,16 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+ clear_dynamic_events
+ SYSTEM="syscalls"
+-EVENT="sys_enter_openat"
++EVENT="sys_enter_chdir"
+ FIELD="filename"
+-EPROBE="eprobe_open"
++EPROBE="eprobe_chdir"
+ OPTIONS="file=+0(\$filename):ustring"
+ echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+@@ -18,20 +18,14 @@ grep -q "$EPROBE" dynamic_events
+ test -d events/eprobes/$EPROBE
+ echo 1 > events/eprobes/$EPROBE/enable
+-ls
++cd /sys/kernel/tracing
+ echo 0 > events/eprobes/$EPROBE/enable
+-content=`grep '^ *ls-' trace | grep 'file='`
+-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
+-
++content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
+ if [ -z "$content" ]; then
+       exit_fail
+ fi
+-if [ ! -z "$nocontent" ]; then
+-      exit_fail
+-fi
+-
+ echo "-:$EPROBE" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+-- 
+2.53.0
+
diff --git a/queue-6.18/selftests-sched_ext-handle-sleeping-task-affinity-ch.patch b/queue-6.18/selftests-sched_ext-handle-sleeping-task-affinity-ch.patch
new file mode 100644 (file)
index 0000000..fa3a99a
--- /dev/null
@@ -0,0 +1,81 @@
+From f568f0154a0abdf922768ea44088083cb82f6ef9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 09:59:55 +0000
+Subject: selftests/sched_ext: Handle sleeping task affinity changes in numa
+ test
+
+From: Kuba Piecuch <jpiecuch@google.com>
+
+[ Upstream commit d4a00d61a5c2c24973175ace5368d1f6acf9bb0a ]
+
+When a sleeping task's affinity is changed, task_cpu(p) can be outside
+of p->cpus_ptr until after select_task_rq() selects a new runqueue for
+the task during wakeup.
+
+Thus, the task's NUMA node determined by numa_select_cpu() can be
+completely outside of the task's cpumask, leading to
+scx_pick_{idle,any}_cpu_node() failing to find an eligible CPU and
+returning -EBUSY. This leads to the numa.bpf.c scheduler abnormally
+exiting with the following message in dmesg:
+
+sched_ext: numa: invalid CPU -16
+   scx_bpf_cpu_node+0x120/0x190
+   bpf_prog_0a34b8e0f515771f_numa_select_cpu+0x108/0x14e
+   bpf__sched_ext_ops_select_cpu+0x4f/0xb4
+   select_task_rq_scx+0xb0/0x210
+   select_task_rq+0xa0/0xd0
+   __try_to_wake_up+0x196/0x650
+   complete_all+0x76/0x100
+   migration_cpu_stop+0x22b/0x300
+   cpu_stopper_thread+0xc1/0x180
+   smpboot_thread_fn+0x16b/0x230
+   kthread+0x2d7/0x350
+   ret_from_fork+0x1c2/0x350
+   ret_from_fork_asm+0x1a/0x30
+
+Make numa_select_cpu() robust against this case by returning @prev_cpu
+if no CPU could be found in the selected NUMA node _and_ we have reason
+to believe that the task's affinity was changed while it was sleeping.
+
+Fixes: 5ae5161820e5 ("selftests/sched_ext: Add NUMA-aware scheduler test")
+Signed-off-by: Kuba Piecuch <jpiecuch@google.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/sched_ext/numa.bpf.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/sched_ext/numa.bpf.c b/tools/testing/selftests/sched_ext/numa.bpf.c
+index a79d86ed54a1b..0ebb6170331bf 100644
+--- a/tools/testing/selftests/sched_ext/numa.bpf.c
++++ b/tools/testing/selftests/sched_ext/numa.bpf.c
+@@ -34,7 +34,8 @@ static bool is_cpu_idle(s32 cpu, int node)
+ s32 BPF_STRUCT_OPS(numa_select_cpu,
+                  struct task_struct *p, s32 prev_cpu, u64 wake_flags)
+ {
+-      int node = __COMPAT_scx_bpf_cpu_node(scx_bpf_task_cpu(p));
++      s32 task_cpu = scx_bpf_task_cpu(p);
++      int node = __COMPAT_scx_bpf_cpu_node(task_cpu);
+       s32 cpu;
+       /*
+@@ -48,6 +49,16 @@ s32 BPF_STRUCT_OPS(numa_select_cpu,
+               cpu = __COMPAT_scx_bpf_pick_any_cpu_node(p->cpus_ptr, node,
+                                               __COMPAT_SCX_PICK_IDLE_IN_NODE);
++      /*
++       * @task_cpu may be outside of p->cpus_ptr if @p's affinity
++       * changed while it was sleeping. This means it's possible for
++       * p->cpus_ptr to not include any CPUs from @node.
++       * If we failed to find a cpu in @node, check if @task_cpu
++       * is outside of p->cpus_ptr and just return @prev_cpu if it is.
++       */
++      if (cpu < 0 && !bpf_cpumask_test_cpu(task_cpu, p->cpus_ptr))
++              return prev_cpu;
++
+       if (is_cpu_idle(cpu, node))
+               scx_bpf_error("CPU %d should be marked as busy", cpu);
+-- 
+2.53.0
+
index 8b6e6d52cf12b83aa2b01e57717dc287c4fa4f33..a8dda1b00fe8ef147d50a09a7aa991d4b03cfa4b 100644 (file)
@@ -5,3 +5,108 @@ selftests-bpf-fail-unbound-udp-on-sockmap-update.patch
 drm-amd-display-add-av-mute-wait-frames-to-dce110_se.patch
 drm-amd-display-check-for-tg-ops-in-dce110_set_avmut.patch
 sched-fair-separate-se-vlag-from-se-vprot.patch
+arm64-dts-qcom-rename-x1e80100-to-hamoa.patch
+arm64-dts-qcom-rework-x1-based-asus-zenbook-a14-s-di.patch
+arm64-dts-qcom-rename-x1p42100-to-purwa.patch
+arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch
+arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch
+xfs-handle-null-b_addr-in-xfs_buf_free.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+selftests-sched_ext-handle-sleeping-task-affinity-ch.patch
+pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch
+pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch
+ovpn-add-missing-rtnl_link_ops-get_size-callback.patch
+arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
+ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch
+ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch
+ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch
+ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch
+ovpn-hash-floated-peer-by-transport-identity-only.patch
+ovpn-disable-ipv4-redirects-on-mp-interfaces.patch
+ovpn-ensure-tcp-vars-are-initialized-first.patch
+ovpn-fix-incorrect-use-of-rcu_access_pointer.patch
+drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
+net-hns3-fix-speed-configuration-residue-after-drive.patch
+revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch
+net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
+pds_core-keep-the-health-thread-stopped-during-reset.patch
+pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch
+netfilter-ipset-switch-ext_size-to-atomic64_t.patch
+ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
+ipvs-return-the-csum-validation-for-forward-hook.patch
+watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch
+btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
+btrfs-update-the-kconfig-string-for-config_btrfs_exp.patch
+btrfs-move-large-data-folios-out-of-experimental-fea.patch
+btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+bpf-split-check_reg_sane_offset-in-two-parts.patch
+bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+devlink-fix-net-namespace-reference-leak-in-reload.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
+vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
+vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch
+hwmon-pmbus_core-use-guard-for-mutex-protection.patch
+hwmon-pmbus-fix-type-confusion-in-notification-logic.patch
+tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
+bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
+net-reduce-indent-of-struct-netdev_queue_mgmt_ops-me.patch
+net-add-bare-bone-queue-configs.patch
+net-pass-queue-rx-page-size-from-memory-provider.patch
+eth-bnxt-store-rx-buffer-size-per-queue.patch
+eth-bnxt-support-qcfg-provided-rx-page-size.patch
+bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch
+xsk-require-at-least-16-bytes-of-tx-metadata.patch
+xsk-pass-tx-metadata-pointer-by-reference.patch
+xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch
+xsk-validate-launch-time-metadata-size.patch
+xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch
+xsk-validate-metadata-when-processing-requests.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+vhost-scsi-validate-t10-pi-scatterlist-counts.patch
+vhost-scsi-reject-feature-changes-after-endpoint.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
+drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch
+hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
+hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
+selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
+net-stmmac-resume-phy-before-hardware-setup-when-ope.patch
+bnge-use-int-for-bnge_fix_rings_count-return-value.patch
+net-mlx5e-fix-bql-reset-on-sq-re-activation.patch
+bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch
+bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch
+bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch
+bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
+bnxt_en-fix-ptp-pps-setting-bug.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
+netfilter-flowtable-consolidate-xmit-path.patch
+netfilter-nf_flow_table-drop-existing-skb-dst-before.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
+net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch
+s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch
+net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
+watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch
+hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
+hwmon-ads7828-fix-external-vref-regulator-handling.patch
+hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch
+hwmon-ltc4282-clamp-negative-current-limits.patch
+hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch
diff --git a/queue-6.18/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch b/queue-6.18/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
new file mode 100644 (file)
index 0000000..da98585
--- /dev/null
@@ -0,0 +1,61 @@
+From 96a6f0678c70b43bf0fa845a1f0d2f8ad095406e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 20:08:06 -0700
+Subject: tcp: do not change rcv_ssthresh in tcp_measure_rcv_mss()
+
+From: Nathan Gao <zcgao@amazon.com>
+
+[ Upstream commit 0e125ecfe20c077625cf0be8d750d5c3abc0dce9 ]
+
+Commit f5da7c45188e ("tcp: adjust rcvq_space after updating scaling
+ratio") replaced the direct window_clamp update in tcp_measure_rcv_mss()
+with a call to tcp_set_window_clamp(), a helper that implements the
+TCP_WINDOW_CLAMP setsockopt. As a side effect, the helper also shrinks
+rcv_ssthresh via __tcp_adjust_rcv_ssthresh().
+
+As a result, each scaling_ratio decrease detected by
+tcp_measure_rcv_mss() also cuts rcv_ssthresh. Elsewhere in TCP,
+rcv_ssthresh is usually cut under memory pressure and grows via
+tcp_grow_window().
+
+Flows whose segment sizes vary keep scaling_ratio oscillating, which
+leads to an unstable rcv_ssthresh: a dip of rcv_ssthresh only recovers
+via tcp_grow_window(), keeping the advertised window at a relatively
+low level even after the ratio itself has recovered, and can even stall
+the sender.
+
+Observed on a customer's proxy gateway after upgrading from kernel 6.1
+to 6.12: in the worst case, rcv_ssthresh was cut in half by a
+scaling_ratio dip. P99 latency jumped from <10ms on 6.1 to ~100ms on
+6.12, and almost returned to the 6.1 level with this patch applied.
+
+Restore the plain WRITE_ONCE() update of window_clamp, as introduced
+in commit a2cbb1603943 ("tcp: Update window clamping condition"), and
+keep the rcvq_space.space adjustment. Now rcv_ssthresh is decoupled from
+scaling_ratio changes in tcp_measure_rcv_mss().
+
+Fixes: f5da7c45188e ("tcp: adjust rcvq_space after updating scaling ratio")
+Signed-off-by: Nathan Gao <zcgao@amazon.com>
+Link: https://patch.msgid.link/20260725030806.28135-1-zcgao@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 8c74fbeb771d5..c1769031a9e93 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -252,7 +252,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
+                               struct tcp_sock *tp = tcp_sk(sk);
+                               val = tcp_win_from_space(sk, sk->sk_rcvbuf);
+-                              tcp_set_window_clamp(sk, val);
++                              WRITE_ONCE(tp->window_clamp, val);
+                               if (tp->window_clamp < tp->rcvq_space.space)
+                                       tp->rcvq_space.space = tp->window_clamp;
+-- 
+2.53.0
+
diff --git a/queue-6.18/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch b/queue-6.18/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
new file mode 100644 (file)
index 0000000..fdccdba
--- /dev/null
@@ -0,0 +1,72 @@
+From 7e86e9b8110ceababbb04802bcc19451390ca755 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:17:38 +0800
+Subject: tcp: fix TFO max_qlen accounting across reuseport migration
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit a0ab2ba83e35159d81cec830a92e885ecf8139be ]
+
+A listener's TCP_FASTOPEN max_qlen stops being accurate and lets through
+far more pending Fast Open requests than it was configured for.
+
+This only shows up with SO_REUSEPORT listener migration, where closing a
+listener hands its still-pending TFO children over to a surviving one.
+
+fastopenq.qlen is charged in tcp_fastopen_create_child() when the child
+is created and uncharged in reqsk_fastopen_remove() when the handshake
+completes.  The uncharge follows rsk_listener of the request the child
+points at, and inet_reqsk_clone() has repointed the child at a new
+request owned by the new listener, so the ++ and the -- land on two
+different sockets.  The new listener's qlen drifts negative and its
+limit no longer binds.
+
+Charge the new listener during migration, like reqsk_queue_migrated()
+already does for queue->young and queue->qlen.
+
+Fixes: 54b92e841937 ("tcp: Migrate TCP_ESTABLISHED/TCP_SYN_RECV sockets in accept queues.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260803061739.134737-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index 1679bfefa560d..5db36e323e683 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -964,11 +964,23 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
+       nreq->rsk_listener = sk;
+-      /* We need not acquire fastopenq->lock
+-       * because the child socket is locked in inet_csk_listen_stop().
+-       */
+-      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
++      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener) {
++              struct fastopen_queue *fastopenq;
++
++              /* reqsk_fastopen_remove() will uncharge nreq->rsk_listener,
++               * that is @sk, so charge it here.  Unlike the listener
++               * being closed, @sk is live and needs its lock.
++               */
++              fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
++              spin_lock_bh(&fastopenq->lock);
++              fastopenq->qlen++;
++              spin_unlock_bh(&fastopenq->lock);
++
++              /* We need not acquire fastopenq->lock
++               * because the child socket is locked in inet_csk_listen_stop().
++               */
+               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
++      }
+       return nreq;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-6.18/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..1bcb7a8
--- /dev/null
@@ -0,0 +1,45 @@
+From b75da59a45af8c4dc2ffcfbe98aa66511fde66c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index f19b504efa5d0..0bb710c5fa601 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -458,7 +458,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-6.18/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-6.18/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..955d905
--- /dev/null
@@ -0,0 +1,53 @@
+From 1c1642d941c8de9becfd7650f85cd40847ebee29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 589456bd8b5f1..4f7ae02df8d3a 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -178,17 +178,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-6.18/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch b/queue-6.18/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch
new file mode 100644 (file)
index 0000000..0165ca3
--- /dev/null
@@ -0,0 +1,61 @@
+From 27b0de378d91ed8119b23b8c4d238ccc68d973a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jul 2026 16:15:37 +0200
+Subject: vdpa/mlx5: Fix buffer length in create_direct_keys()
+
+From: Christian Borntraeger <borntraeger@linux.ibm.com>
+
+[ Upstream commit 727e1f569855df83579edbd73dcb4a0723543a12 ]
+
+We have seen in our CI the following KASAN message:
+BUG: KASAN: slab-out-of-bounds in cmd_exec+0x550/0xca0 [mlx5_core]
+Read of size 272 at addr 0000000176795020 by task qemu-system-s39/82764
+[...]
+[<000011388ab3a7a0>] cmd_exec+0x550/0xca0 [mlx5_core]
+[<000011388ab3b61c>] mlx5_cmd_exec_cb+0x25c/0x4f0 [mlx5_core]
+[<000011388b21e82e>] mlx5_vdpa_exec_async_cmds+0x22e/0x5e0 [mlx5_vdpa]
+[<000011388b21fd44>] create_direct_keys+0x954/0xef0 [mlx5_vdpa]
+[...]
+The buggy address is located 4128 bytes inside of
+allocated 4384-byte region [0000000176794000, 0000000176795120)
+
+So in essence we read 16 bytes beyond 4384-byte allocation.
+create_direct_keys calculates the pointer and length for in and out
+buffers.
+The size calculation for in includes the entire structure
+size (out + in + mtt[]) but the pointer passed to cmd_exec points only
+to the 'in' field, skipping the 'out' field.
+
+This causes mlx5_copy_to_msg() to read beyond the allocated buffer
+by sizeof(out) bytes when copying command data.
+
+Properly calculate the input size to match the pointer and allocation size.
+
+Fixes: 0071b138d44a ("vdpa/mlx5: Create direct MKEYs in parallel")
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Tested-by: Dragos Tatulea <dtatulea@nvidia.com>
+Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <20260706141537.3510294-1-borntraeger@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/core/mr.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
+index 8870a7169267e..2450440dae2e1 100644
+--- a/drivers/vdpa/mlx5/core/mr.c
++++ b/drivers/vdpa/mlx5/core/mr.c
+@@ -234,7 +234,8 @@ static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *
+               cmds[i].out = cmd_mem->out;
+               cmds[i].outlen = sizeof(cmd_mem->out);
+               cmds[i].in = cmd_mem->in;
+-              cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount);
++              cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount) -
++                              offsetof(struct mlx5_create_mkey_mem, in);
+               fill_create_direct_mr(mvdev, dmr, cmd_mem);
+-- 
+2.53.0
+
diff --git a/queue-6.18/vhost-scsi-reject-feature-changes-after-endpoint.patch b/queue-6.18/vhost-scsi-reject-feature-changes-after-endpoint.patch
new file mode 100644 (file)
index 0000000..ab41f51
--- /dev/null
@@ -0,0 +1,102 @@
+From a3a430f3c447e06a0c139c2ebe5c66e1dbd71b35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Jul 2026 22:43:14 +0800
+Subject: vhost-scsi: reject feature changes after endpoint
+
+From: Jia Jia <physicalmtea@gmail.com>
+
+[ Upstream commit 42bc45df5905e2b7dccb72adaf7730f66cfbe03f ]
+
+vhost_scsi_setup_vq_cmds() runs from VHOST_SCSI_SET_ENDPOINT and allocates
+each command's protection scatterlist array (prot_sgl) according to the
+acknowledged VIRTIO_SCSI_F_T10_PI bit.  The command pools are not rebuilt
+when VHOST_SET_FEATURES changes that bit later.
+
+Although virtio feature bits must not change after feature negotiation,
+vhost_scsi_set_features() currently accepts such a request after the
+endpoint is active and updates acked_features.  Enabling T10-PI after
+endpoint setup therefore leaves prot_sgl NULL while the I/O path follows
+the new feature bit.
+
+For a 129-page protection payload, vhost_scsi_mapal() passes the missing
+first chunk to sg_alloc_table_chained():
+
+  sg_alloc_table_chained(table, 129, first_chunk=NULL,
+                         nents_first_chunk=inline_sg_cnt)
+
+sg_pool_index() then hits:
+
+  BUG_ON(nents > SG_CHUNK_SIZE);   /* 129 > 128 */
+
+The kernel reported the following call trace and register state:
+
+  Call Trace:
+   <TASK>
+   ? __sg_alloc_table+0x1d8/0x250
+   ? __pfx_vhost_run_work_list+0x10/0x10 [vhost]
+   sg_alloc_table_chained+0x59/0xf0
+   ? __pfx_sg_pool_alloc+0x10/0x10
+   ? vhost_scsi_calc_sgls.constprop.0+0x43/0x60 [vhost_scsi]
+   vhost_scsi_handle_vq+0xf02/0x1700 [vhost_scsi]
+   ? __pfx_vhost_scsi_handle_vq+0x10/0x10 [vhost_scsi]
+   vhost_scsi_handle_kick+0x37/0x50 [vhost_scsi]
+   vhost_run_work_list+0x8e/0xd0 [vhost]
+   vhost_task_fn+0xe1/0x210
+   ret_from_fork+0x348/0x540
+   </TASK>
+
+  RIP: 0010:0x4
+  CR2 = 0x4
+  RSP: 0018:ffffc90000dbf940 EFLAGS: 00010202
+  RAX: ffffffff82396810 RBX: ffff88811dc28b80 RCX: 0000000000000000
+  RDX: 0000000000000000 RSI: 0000000000000820 RDI: 0000000000000081
+
+VHOST_F_LOG_ALL is a vhost-specific runtime feature and remains the only
+exception.
+
+Reject changes to any feature other than VHOST_F_LOG_ALL while the
+endpoint is active.  This preserves the existing runtime log toggle while
+preventing feature-dependent command resources and data-path state from
+becoming inconsistent.  Userspace must clear the endpoint before changing
+any other negotiated feature and set the endpoint up again afterward.
+
+Fixes: bf2d650391be ("vhost-scsi: Allocate T10 PI structs only when enabled")
+Signed-off-by: Jia Jia <physicalmtea@gmail.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <20260726144314.1652934-1-physicalmtea@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/scsi.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index 65a57de0080ef..29716ce714554 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -2231,6 +2231,7 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
+ {
+       struct vhost_virtqueue *vq;
+       bool is_log, was_log;
++      u64 old_features;
+       int i;
+       if (features & ~VHOST_SCSI_FEATURES)
+@@ -2246,6 +2247,14 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
+       if (!vs->dev.nvqs)
+               goto out;
++      old_features = vs->vqs[0].vq.acked_features;
++      if (vs->vs_tpg &&
++          ((features ^ old_features) &
++           ~(1ULL << VHOST_F_LOG_ALL))) {
++              mutex_unlock(&vs->dev.mutex);
++              return -EBUSY;
++      }
++
+       is_log = features & (1 << VHOST_F_LOG_ALL);
+       /*
+        * All VQs should have same feature.
+-- 
+2.53.0
+
diff --git a/queue-6.18/vhost-scsi-validate-t10-pi-scatterlist-counts.patch b/queue-6.18/vhost-scsi-validate-t10-pi-scatterlist-counts.patch
new file mode 100644 (file)
index 0000000..ec270e5
--- /dev/null
@@ -0,0 +1,63 @@
+From de1ecc4d02139e98f84174a4139e1997337d605c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 16:18:41 +0800
+Subject: vhost-scsi: Validate T10 PI scatterlist counts
+
+From: Linfeng Sun <slf@hdu.edu.cn>
+
+[ Upstream commit d876c493fc4b811941bfeb4c80beb2dfc4bf025e ]
+
+When T10 PI is negotiated, vhost-scsi splits protection bytes from
+the data iterator before mapping the request scatterlists. A malformed
+request can claim protection bytes that cover or exceed the full payload
+length. The former leaves no data bytes to map, while the latter
+underflows exp_data_len before advancing the iterator. Both cases can let
+a zero data SGL count reach sg_alloc_table_chained(), which triggers
+BUG_ON(!nents).
+
+Reject protection lengths that cover or exceed the payload before
+subtracting prot_bytes and advancing the iterator. Also propagate
+negative errors from the protection SGL calculation before calling the
+allocator, matching the data SGL path.
+
+Fixes: bca939d5bcd0 ("vhost-scsi: Dynamically allocate scatterlists")
+Suggested-by: Jia Jia <physicalmtea@gmail.com>
+Signed-off-by: Jia Jia <physicalmtea@gmail.com>
+Assisted-by: OpenAI-Codex:GPT-5
+Signed-off-by: Linfeng Sun <linfeng.sun.dev@gmail.com>
+Message-ID: <20260727081841.923151-1-slf@hdu.edu.cn>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/scsi.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index 98e4f68f4e3cb..65a57de0080ef 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -971,6 +971,9 @@ vhost_scsi_mapal(struct vhost_scsi *vs, struct vhost_scsi_cmd *cmd,
+       if (prot_bytes) {
+               sgl_count = vhost_scsi_calc_sgls(prot_iter, prot_bytes,
+                                                VHOST_SCSI_PREALLOC_PROT_SGLS);
++              if (sgl_count < 0)
++                      return sgl_count;
++
+               cmd->prot_table.sgl = cmd->prot_sgl;
+               ret = sg_alloc_table_chained(&cmd->prot_table, sgl_count,
+                                            cmd->prot_table.sgl,
+@@ -1416,6 +1419,11 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
+                        * actual data payload length.
+                        */
+                       if (prot_bytes) {
++                              if (prot_bytes >= exp_data_len) {
++                                      vq_err(vq, "Protection data exceeds payload length\n");
++                                      goto err;
++                              }
++
+                               exp_data_len -= prot_bytes;
+                               prot_iter = data_iter;
+                               iov_iter_truncate(&prot_iter, prot_bytes);
+-- 
+2.53.0
+
diff --git a/queue-6.18/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch b/queue-6.18/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
new file mode 100644 (file)
index 0000000..910b20f
--- /dev/null
@@ -0,0 +1,56 @@
+From ac480eb9d1cc42e8a00eb58acd9b0e7df24e0e8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:02:02 -0700
+Subject: vhost/vdpa: reject overflowing PA map page counts on 32-bit
+
+From: Yousef Alhouseen <alhouseenyousef@gmail.com>
+
+[ Upstream commit 0619aaa34c0c2a2dcb07f0e9c8a34e7efb8c4cdf ]
+
+vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
+size before computing the number of pages to pin. On 32-bit systems,
+where unsigned long is narrower than u64, that addition can overflow and
+the code can pin and map fewer pages than the requested IOTLB range.
+
+Reject sizes that overflow the unsigned long page-count calculation.
+
+Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and vhost_vdpa_pa_unmap()")
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index a6c6c28bf2d9d..4c988f30a55c3 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -1100,6 +1100,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       unsigned int gup_flags = FOLL_LONGTERM;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
++      unsigned long page_offset;
+       u64 start = iova;
+       long pinned;
+       int ret = 0;
+@@ -1112,7 +1113,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       if (perm & VHOST_ACCESS_WO)
+               gup_flags |= FOLL_WRITE;
+-      npages = PFN_UP(size + (iova & ~PAGE_MASK));
++      page_offset = iova & ~PAGE_MASK;
++      if (size > ULONG_MAX - page_offset) {
++              ret = -EINVAL;
++              goto free;
++      }
++
++      npages = PFN_UP(size + page_offset);
+       if (!npages) {
+               ret = -EINVAL;
+               goto free;
+-- 
+2.53.0
+
diff --git a/queue-6.18/watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch b/queue-6.18/watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch
new file mode 100644 (file)
index 0000000..4095fcb
--- /dev/null
@@ -0,0 +1,51 @@
+From 91152754adf84a760e52e3146a7b1c425ce9c7d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:13 +0800
+Subject: watchdog: at91sam9_wdt: prevent timer rearm during teardown
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 8444d66aa6b6e7fe0a26fa1a00a11cb4d0523783 ]
+
+at91_ping() rearms the watchdog timer from its callback. timer_delete()
+neither waits for a running callback nor prevents it from rearming the
+timer, so probe failure or driver removal can leave the timer accessing the
+devm-allocated at91wdt after it has been freed.
+
+Use timer_shutdown_sync() on both teardown paths. It waits for a running
+callback and rejects any attempt by the callback to rearm the timer.
+
+Fixes: 5161b31dc39a ("watchdog: at91sam9_wdt: better watchdog support")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Link: https://lore.kernel.org/r/20260806060613.1830-1-getshell@seu.edu.cn
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/at91sam9_wdt.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
+index aba66b8e9d033..80ba04df54adf 100644
+--- a/drivers/watchdog/at91sam9_wdt.c
++++ b/drivers/watchdog/at91sam9_wdt.c
+@@ -242,7 +242,7 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
+       return 0;
+ out_stop_timer:
+-      timer_delete(&wdt->timer);
++      timer_shutdown_sync(&wdt->timer);
+       return err;
+ }
+@@ -378,7 +378,7 @@ static void at91wdt_remove(struct platform_device *pdev)
+       watchdog_unregister_device(&wdt->wdd);
+       pr_warn("I quit now, hardware will probably reboot!\n");
+-      timer_delete(&wdt->timer);
++      timer_shutdown_sync(&wdt->timer);
+ }
+ #if defined(CONFIG_OF)
+-- 
+2.53.0
+
diff --git a/queue-6.18/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch b/queue-6.18/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch
new file mode 100644 (file)
index 0000000..19e8e05
--- /dev/null
@@ -0,0 +1,68 @@
+From e15d0c58114a685cc347911a36b06033976ddfe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:36:28 +0300
+Subject: watchdog: bd96801_wdt: Fix timeout for enabled WDG
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit 1246aa2b6ccc8944676bd24ff3e37cc56b93b51b ]
+
+When watchdog is enabled at the probe time, the bd96801 driver retrieves
+the timeout configuration from the registers to set-up the heart-beat
+values.
+
+As Sashiko pointed out at
+https://lore.kernel.org/all/20260722085819.495211F000E9@smtp.kernel.org/
+the timeout values are incorrectly computed in driver, resulting wrong
+heartbeat. This leads to devere problems if watchdog was enabled at probe
+time.
+
+According to the data-sheet, the "too fast" ping limit is configured as
+multiple of FASTNG_MIN. Furthermore, the "too slow" ping limit is
+configured as multiples of "too fast" timeout. The FASTNG_MIN is set to
+11, meaning 1.1 mS and "too fast" and "too slow" limits are computed from
+this. Hence, converting the limits to mS should be done by dividing by 10,
+not by dividing by USEC_PER_MSEC.
+
+Fix this by dividing the timeout values with correct scaling factor.
+
+While at it, fix whitespace problem (double empty line).
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Fixes: 09dad69757b6 ("watchdog: ROHM BD96801 PMIC WDG driver")
+Link: https://lore.kernel.org/r/amxskHmQbi9v-8_l@mva-rohm
+[groeck: Added reference to whitespace change to description]
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/bd96801_wdt.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/watchdog/bd96801_wdt.c b/drivers/watchdog/bd96801_wdt.c
+index 12b74fd2bc052..a25b7cf1488b2 100644
+--- a/drivers/watchdog/bd96801_wdt.c
++++ b/drivers/watchdog/bd96801_wdt.c
+@@ -169,7 +169,6 @@ static int bd96801_set_wdt_mode(struct wdtbd96801 *w, unsigned int hw_margin,
+       int fastng, slowng, type, ret, reg, mask;
+       struct device *dev = w->dev;
+-
+       if (hw_margin_min * 1000 > FASTNG_MAX_US) {
+               dev_err(dev, "Unsupported fast timeout %u uS [max %u]\n",
+                       hw_margin_min * 1000, FASTNG_MAX_US);
+@@ -258,10 +257,10 @@ static int bd96801_set_heartbeat_from_hw(struct wdtbd96801 *w,
+       fast = FASTNG_MIN << sel;
+       sel = (val & BD96801_WD_RATIO_MASK) + 1;
+-      w->wdt.max_hw_heartbeat_ms = (fast << sel) / USEC_PER_MSEC;
++      w->wdt.max_hw_heartbeat_ms = (fast << sel) / 10;
+       if ((conf_reg & BD96801_WD_TYPE_MASK) == BD96801_WD_TYPE_WIN)
+-              w->wdt.min_hw_heartbeat_ms = fast / USEC_PER_MSEC;
++              w->wdt.min_hw_heartbeat_ms = fast / 10;
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/xfs-handle-null-b_addr-in-xfs_buf_free.patch b/queue-6.18/xfs-handle-null-b_addr-in-xfs_buf_free.patch
new file mode 100644 (file)
index 0000000..b72b681
--- /dev/null
@@ -0,0 +1,53 @@
+From dfde8f3107af91bc697d1bb1ad7ffc7e3fd31309 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jul 2026 23:11:24 +0800
+Subject: xfs: handle NULL b_addr in xfs_buf_free
+
+From: Yun Zhou <yun.zhou@windriver.com>
+
+[ Upstream commit d852729c5f4f830fbe7413df032e29459b3daf83 ]
+
+When xfs_buf_alloc_backing_mem() fails, xfs_buf_free() is called with
+bp->b_addr still NULL.  The code falls through to the folio_put path
+which calls virt_to_folio(NULL), dereferencing an invalid address and
+causing a kernel crash.
+
+ Call Trace:
+  xfs_buf_free+0x25f/0x510
+  xfs_buf_alloc+0xc98/0x19b0
+  xfs_buf_find_insert+0x55/0x14d0
+  xfs_buf_get_map+0x122b/0x17c0
+  xfbtree_init_leaf_block+0x11c/0x4a0
+  xfbtree_init+0x1bb/0x460
+  xrep_rmap_setup_scan+0x100/0x1f0
+  xrep_rmapbt+0x41/0xc0
+
+Fix this by skipping folio_put() when bp->b_addr is NULL.
+
+Fixes: 5076a6040ca1 ("xfs: support in-memory buffer cache targets")
+Reported-by: syzbot+94c22d92f72f5a235b7d@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=94c22d92f72f5a235b7d
+Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_buf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
+index 1ca95ef46a73d..441631c736c1c 100644
+--- a/fs/xfs/xfs_buf.c
++++ b/fs/xfs/xfs_buf.c
+@@ -117,7 +117,7 @@ xfs_buf_free(
+               vfree(bp->b_addr);
+       else if (bp->b_flags & _XBF_KMEM)
+               kfree(bp->b_addr);
+-      else
++      else if (bp->b_addr)
+               folio_put(virt_to_folio(bp->b_addr));
+       call_rcu(&bp->b_rcu, xfs_buf_free_callback);
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch b/queue-6.18/xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch
new file mode 100644 (file)
index 0000000..c48a8bd
--- /dev/null
@@ -0,0 +1,88 @@
+From a41dd9dbb3f50c2e46cd72c66491ba36c3179b14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:56 -0700
+Subject: xsk: clear metadata pointer when no timestamp is requested
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 9f60a67df8d3c862503bee62bada8e7089cba438 ]
+
+User space can change metadata flags after request processing. Rereading
+them during completion can therefore make the kernel write a timestamp
+that was not requested when the packet was submitted.
+
+Clear the metadata pointer during request processing unless timestamp
+completion is requested. Completion handling can then use the pointer
+itself instead of rereading the flags.
+
+On the mlx5 multi-packet WQE path metadata is evaluated per batch:
+xsk_tx_metadata_request() runs only for the descriptor that starts a
+session, just like the checksum offload that is applied once through the
+shared WQE. Only that descriptor's pointer is reset, so completion
+handling can record a timestamp for the other descriptors of the session
+regardless of their own XDP_TXMD_FLAGS_TIMESTAMP bit. The write stays
+inside the metadata area; the single-WQE, other zero-copy, and generic
+paths reset the pointer per descriptor and are unaffected.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-4-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xdp_sock.h | 14 ++++++++++----
+ net/xdp/xsk.c          |  2 ++
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index b93d6bd368d00..e14e575178940 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -140,13 +140,16 @@ void __xsk_map_flush(struct list_head *flush_list);
+ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+                                           struct xsk_tx_metadata_compl *compl)
+ {
++      compl->tx_timestamp = NULL;
++
+       if (!meta)
+               return;
+-      if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
+-              compl->tx_timestamp = &meta->completion.tx_timestamp;
+-      else
+-              compl->tx_timestamp = NULL;
++      /* we can only arrive here if the completion timestamp has been
++       * requested via XDP_TXMD_FLAGS_TIMESTAMP, see xsk_tx_metadata_request
++       */
++
++      compl->tx_timestamp = &meta->completion.tx_timestamp;
+ }
+ /**
+@@ -181,6 +184,9 @@ static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+               if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
+                       ops->tmo_request_checksum(meta->request.csum_start,
+                                                 meta->request.csum_offset, priv);
++
++      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++              *pmeta = NULL;
+ }
+ /**
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 70c57c5d8e1da..3b82fb850bee3 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -730,6 +730,8 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+       if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+               skb->skb_mstamp_ns = meta->request.launch_time;
++      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++              meta = NULL;
+       xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch b/queue-6.18/xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch
new file mode 100644 (file)
index 0000000..c683cf7
--- /dev/null
@@ -0,0 +1,150 @@
+From abcfa6d57a0bacd1d65dd67279105ab9cae86a0d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:58 -0700
+Subject: xsk: move xsk_tx_metadata_request() to xdp_sock_drv.h
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit ddd0d6c5bfe2fef7c7cf31f62265f29b7b9eb9ef ]
+
+xsk_tx_metadata_request() must validate metadata with
+xsk_buff_valid_tx_metadata(), which is defined in xdp_sock_drv.h. Move the
+helper there before adding that dependency. All callers already include
+the destination header, so this has no functional effect.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-6-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xdp_sock.h     | 43 --------------------------------------
+ include/net/xdp_sock_drv.h | 43 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 43 insertions(+), 43 deletions(-)
+
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index e14e575178940..8bf17ba6c3bd7 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -152,43 +152,6 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+       compl->tx_timestamp = &meta->completion.tx_timestamp;
+ }
+-/**
+- *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
+- *  and call appropriate xsk_tx_metadata_ops operation.
+- *  @pmeta: pointer to pointer to AF_XDP metadata area
+- *  @ops: pointer to struct xsk_tx_metadata_ops
+- *  @priv: pointer to driver-private aread
+- *
+- *  This function should be called by the networking device when
+- *  it prepares AF_XDP egress packet.
+- */
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
+-{
+-      const struct xsk_tx_metadata *meta = *pmeta;
+-
+-      if (!meta)
+-              return;
+-
+-      if (ops->tmo_request_launch_time)
+-              if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+-                      ops->tmo_request_launch_time(meta->request.launch_time,
+-                                                   priv);
+-
+-      if (ops->tmo_request_timestamp)
+-              if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
+-                      ops->tmo_request_timestamp(priv);
+-
+-      if (ops->tmo_request_checksum)
+-              if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
+-                      ops->tmo_request_checksum(meta->request.csum_start,
+-                                                meta->request.csum_offset, priv);
+-
+-      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
+-              *pmeta = NULL;
+-}
+-
+ /**
+  *  xsk_tx_metadata_complete - Evaluate AF_XDP TX metadata at completion
+  *  and call appropriate xsk_tx_metadata_ops operation.
+@@ -232,12 +195,6 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+ {
+ }
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
+-{
+-}
+-
+ static inline void xsk_tx_metadata_complete(struct xsk_tx_metadata_compl *compl,
+                                           const struct xsk_tx_metadata_ops *ops,
+                                           void *priv)
+diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
+index ce8315f049684..6d4f65b0ed53a 100644
+--- a/include/net/xdp_sock_drv.h
++++ b/include/net/xdp_sock_drv.h
+@@ -267,6 +267,43 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+       return !(*flags & ~XDP_TXMD_FLAGS_VALID);
+ }
++/**
++ *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
++ *  and call appropriate xsk_tx_metadata_ops operation.
++ *  @pmeta: pointer to pointer to AF_XDP metadata area
++ *  @ops: pointer to struct xsk_tx_metadata_ops
++ *  @priv: pointer to driver-private aread
++ *
++ *  This function should be called by the networking device when
++ *  it prepares AF_XDP egress packet.
++ */
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
++                                         const struct xsk_tx_metadata_ops *ops,
++                                         void *priv)
++{
++      const struct xsk_tx_metadata *meta = *pmeta;
++
++      if (!meta)
++              return;
++
++      if (ops->tmo_request_launch_time)
++              if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++                      ops->tmo_request_launch_time(meta->request.launch_time,
++                                                   priv);
++
++      if (ops->tmo_request_timestamp)
++              if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
++                      ops->tmo_request_timestamp(priv);
++
++      if (ops->tmo_request_checksum)
++              if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
++                      ops->tmo_request_checksum(meta->request.csum_start,
++                                                meta->request.csum_offset, priv);
++
++      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++              *pmeta = NULL;
++}
++
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+@@ -479,6 +516,12 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+       return false;
+ }
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
++                                         const struct xsk_tx_metadata_ops *ops,
++                                         void *priv)
++{
++}
++
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-pass-tx-metadata-pointer-by-reference.patch b/queue-6.18/xsk-pass-tx-metadata-pointer-by-reference.patch
new file mode 100644 (file)
index 0000000..274aad9
--- /dev/null
@@ -0,0 +1,203 @@
+From 4ef0c56635e67b82407fc88eb2f91af4381ae332 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:55 -0700
+Subject: xsk: pass TX metadata pointer by reference
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 19366db6dfccac9b0867a151678cd7b89fb8fd99 ]
+
+Completion handling needs to know whether a timestamp was requested when
+the metadata was processed. Let xsk_tx_metadata_request() update the
+caller's metadata pointer so that decision can be carried forward without
+rereading user-controlled flags.
+
+This only changes the interface; behavior remains unchanged.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-3-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igc/igc_main.c          |  2 +-
+ drivers/net/ethernet/mellanox/mlx5/core/en.h       |  2 +-
+ drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c   | 14 +++++++++-----
+ drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h   |  4 ++--
+ .../net/ethernet/mellanox/mlx5/core/en/xsk/tx.c    |  2 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  2 +-
+ include/net/libeth/xsk.h                           |  2 +-
+ include/net/xdp_sock.h                             |  8 +++++---
+ 8 files changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index 4ca242ebf3e34..f69523e35ac10 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -3082,7 +3082,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
+               meta_req.tx_buffer = bi;
+               meta_req.meta = meta;
+               meta_req.used_desc = 0;
+-              xsk_tx_metadata_request(meta, &igc_xsk_tx_metadata_ops,
++              xsk_tx_metadata_request(&meta, &igc_xsk_tx_metadata_ops,
+                                       &meta_req);
+               /* xsk_tx_metadata_request() may have updated next_to_use */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+index 3d8276a0692fc..91653b69328ee 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+@@ -477,7 +477,7 @@ typedef int (*mlx5e_fp_xmit_xdp_frame_check)(struct mlx5e_xdpsq *);
+ typedef bool (*mlx5e_fp_xmit_xdp_frame)(struct mlx5e_xdpsq *,
+                                       struct mlx5e_xmit_data *,
+                                       int,
+-                                      struct xsk_tx_metadata *);
++                                      struct xsk_tx_metadata **);
+ struct mlx5e_xdpsq {
+       /* data path */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+index 5322964214b22..e467a7b067c7a 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+@@ -451,11 +451,11 @@ INDIRECT_CALLABLE_SCOPE int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq
+ INDIRECT_CALLABLE_SCOPE bool
+ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+-                   int check_result, struct xsk_tx_metadata *meta);
++                   int check_result, struct xsk_tx_metadata **meta);
+ INDIRECT_CALLABLE_SCOPE bool
+ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+-                         int check_result, struct xsk_tx_metadata *meta)
++                         int check_result, struct xsk_tx_metadata **meta)
+ {
+       struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
+       struct mlx5e_xdpsq_stats *stats = sq->stats;
+@@ -503,7 +503,10 @@ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptx
+                * and it's safe to complete it at any time.
+                */
+               mlx5e_xdp_mpwqe_session_start(sq);
+-              xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, &session->wqe->eth);
++              if (meta)
++                      xsk_tx_metadata_request(meta,
++                                              &mlx5e_xsk_tx_metadata_ops,
++                                              &session->wqe->eth);
+       }
+       mlx5e_xdp_mpwqe_add_dseg(sq, p, stats);
+@@ -534,7 +537,7 @@ INDIRECT_CALLABLE_SCOPE int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq)
+ INDIRECT_CALLABLE_SCOPE bool
+ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+-                   int check_result, struct xsk_tx_metadata *meta)
++                   int check_result, struct xsk_tx_metadata **meta)
+ {
+       struct mlx5e_xmit_data_frags *xdptxdf =
+               container_of(xdptxd, struct mlx5e_xmit_data_frags, xd);
+@@ -648,7 +651,8 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+       sq->pc += num_wqebbs;
+-      xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
++      if (meta)
++              xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
+       sq->doorbell_cseg = cseg;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+index 46ab0a9e8cddb..1a9eb77981cc3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+@@ -113,11 +113,11 @@ extern const struct xsk_tx_metadata_ops mlx5e_xsk_tx_metadata_ops;
+ INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq,
+                                                         struct mlx5e_xmit_data *xdptxd,
+                                                         int check_result,
+-                                                        struct xsk_tx_metadata *meta));
++                                                        struct xsk_tx_metadata **meta));
+ INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq,
+                                                   struct mlx5e_xmit_data *xdptxd,
+                                                   int check_result,
+-                                                  struct xsk_tx_metadata *meta));
++                                                  struct xsk_tx_metadata **meta));
+ INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq));
+ INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq));
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
+index a59199ed590da..827538d92ac23 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
+@@ -103,7 +103,7 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget)
+               ret = INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe,
+                                     mlx5e_xmit_xdp_frame, sq, &xdptxd,
+-                                    check_result, meta);
++                                    check_result, &meta);
+               if (unlikely(!ret)) {
+                       if (sq->mpwqe.wqe)
+                               mlx5e_xdp_mpwqe_complete(sq);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 3be0b79532496..3380ce960de24 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2574,7 +2574,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+               meta_req.set_ic = &set_ic;
+               meta_req.tbs = tx_q->tbs;
+               meta_req.edesc = &tx_q->dma_entx[entry];
+-              xsk_tx_metadata_request(meta, &stmmac_xsk_tx_metadata_ops,
++              xsk_tx_metadata_request(&meta, &stmmac_xsk_tx_metadata_ops,
+                                       &meta_req);
+               if (set_ic) {
+                       tx_q->tx_count_frames = 0;
+diff --git a/include/net/libeth/xsk.h b/include/net/libeth/xsk.h
+index 481a7b28e6f24..1a55daa32cf16 100644
+--- a/include/net/libeth/xsk.h
++++ b/include/net/libeth/xsk.h
+@@ -205,7 +205,7 @@ __libeth_xsk_xmit_fill_buf_md(const struct xdp_desc *xdesc,
+       BUILD_BUG_ON(!__builtin_constant_p(tmo == libeth_xsktmo));
+       tmo = tmo == libeth_xsktmo ? &__libeth_xsktmo : tmo;
+-      xsk_tx_metadata_request(ctx.meta, tmo, &desc);
++      xsk_tx_metadata_request(&ctx.meta, tmo, &desc);
+       return desc;
+ }
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index 8a0967af8f0c4..b93d6bd368d00 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -152,17 +152,19 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+ /**
+  *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
+  *  and call appropriate xsk_tx_metadata_ops operation.
+- *  @meta: pointer to AF_XDP metadata area
++ *  @pmeta: pointer to pointer to AF_XDP metadata area
+  *  @ops: pointer to struct xsk_tx_metadata_ops
+  *  @priv: pointer to driver-private aread
+  *
+  *  This function should be called by the networking device when
+  *  it prepares AF_XDP egress packet.
+  */
+-static inline void xsk_tx_metadata_request(const struct xsk_tx_metadata *meta,
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+                                          const struct xsk_tx_metadata_ops *ops,
+                                          void *priv)
+ {
++      const struct xsk_tx_metadata *meta = *pmeta;
++
+       if (!meta)
+               return;
+@@ -224,7 +226,7 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+ {
+ }
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata *meta,
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+                                          const struct xsk_tx_metadata_ops *ops,
+                                          void *priv)
+ {
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-require-at-least-16-bytes-of-tx-metadata.patch b/queue-6.18/xsk-require-at-least-16-bytes-of-tx-metadata.patch
new file mode 100644 (file)
index 0000000..d0d27b0
--- /dev/null
@@ -0,0 +1,45 @@
+From 2a16becdb05a95ddae2dd899f162164424231361 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:54 -0700
+Subject: xsk: require at least 16 bytes of TX metadata
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 1bb30b181d9f0484e141f8411e15ed906d5c6780 ]
+
+AF_XDP accepts a TX metadata length as small as eight bytes, but every
+supported request needs the flags plus at least one eight-byte request
+field. Such short metadata also lets the kernel read beyond the registered
+area.
+
+Require 16 bytes rather than sizeof(struct xsk_tx_metadata) to preserve
+compatibility with applications that do not use launch-time metadata.
+
+Fixes: 341ac980eab9 ("xsk: Support tx_metadata_len")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reported-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Link: https://lore.kernel.org/netdev/20260720155210.34229-1-blbllhy@gmail.com/
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-2-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xdp_umem.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
+index 9ec7bd948acc7..81ffda5501078 100644
+--- a/net/xdp/xdp_umem.c
++++ b/net/xdp/xdp_umem.c
+@@ -209,6 +209,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
+       if (mr->flags & XDP_UMEM_TX_METADATA_LEN) {
+               if (mr->tx_metadata_len >= 256 || mr->tx_metadata_len % 8)
+                       return -EINVAL;
++              if (mr->tx_metadata_len < 16)
++                      return -EINVAL;
+               umem->tx_metadata_len = mr->tx_metadata_len;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-validate-launch-time-metadata-size.patch b/queue-6.18/xsk-validate-launch-time-metadata-size.patch
new file mode 100644 (file)
index 0000000..850dae8
--- /dev/null
@@ -0,0 +1,117 @@
+From cfd011a88a3249cdfe4769db8f037c6d218dddb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:57 -0700
+Subject: xsk: validate launch-time metadata size
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 439ce2dddf3d22129b9113a7881637256a35e936 ]
+
+Launch-time metadata extends beyond the first 16 bytes of struct
+xsk_tx_metadata. Reject the request when the registered metadata area does
+not contain the complete field.
+
+Snapshot the validated flags for the generic transmit path and use that
+snapshot for request and completion processing, avoiding inconsistent
+decisions if user space changes the flags concurrently.
+
+Note that only xsk_skb_metadata is properly using the flags,
+__xsk_buff_get_metadata ignores them. Next commits address that.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-5-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xdp_sock_drv.h | 17 +++++++++++++----
+ net/xdp/xsk.c              | 11 ++++++-----
+ 2 files changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
+index dd1d3a6e1b780..ce8315f049684 100644
+--- a/include/net/xdp_sock_drv.h
++++ b/include/net/xdp_sock_drv.h
+@@ -256,21 +256,28 @@ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+       0)
+ static inline bool
+-xsk_buff_valid_tx_metadata(const struct xsk_tx_metadata *meta)
++xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
++                         const struct xsk_tx_metadata *meta, u64 *flags)
+ {
+-      return !(meta->flags & ~XDP_TXMD_FLAGS_VALID);
++      *flags = READ_ONCE(meta->flags);
++      if (*flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++              if (pool->tx_metadata_len <
++                  offsetofend(struct xsk_tx_metadata, request.launch_time))
++                      return false;
++      return !(*flags & ~XDP_TXMD_FLAGS_VALID);
+ }
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+       struct xsk_tx_metadata *meta;
++      u64 flags;
+       if (!pool->tx_metadata_len)
+               return NULL;
+       meta = data - pool->tx_metadata_len;
+-      if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
++      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
+               return NULL; /* no way to signal the error to the user */
+       return meta;
+@@ -465,7 +472,9 @@ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+       return (struct xdp_desc_ctx){ };
+ }
+-static inline bool xsk_buff_valid_tx_metadata(struct xsk_tx_metadata *meta)
++static inline bool
++xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
++                         const struct xsk_tx_metadata *meta, u64 *flags)
+ {
+       return false;
+ }
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 3b82fb850bee3..ff93fd7ac6317 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -699,15 +699,16 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+ {
+       struct xsk_tx_metadata *meta = NULL;
+       u16 csum_start, csum_offset;
++      u64 flags;
+       if (unlikely(pool->tx_metadata_len == 0))
+               return -EINVAL;
+       meta = buffer - pool->tx_metadata_len;
+-      if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
++      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
+               return -EINVAL;
+-      if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) {
++      if (flags & XDP_TXMD_FLAGS_CHECKSUM) {
+               csum_start = READ_ONCE(meta->request.csum_start);
+               csum_offset = READ_ONCE(meta->request.csum_offset);
+@@ -728,9 +729,9 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+               }
+       }
+-      if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+-              skb->skb_mstamp_ns = meta->request.launch_time;
+-      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++      if (flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++              skb->skb_mstamp_ns = READ_ONCE(meta->request.launch_time);
++      if (!(flags & XDP_TXMD_FLAGS_TIMESTAMP))
+               meta = NULL;
+       xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta);
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-validate-metadata-when-processing-requests.patch b/queue-6.18/xsk-validate-metadata-when-processing-requests.patch
new file mode 100644 (file)
index 0000000..2b90377
--- /dev/null
@@ -0,0 +1,224 @@
+From 5afc7703d0517d79788630ecac877e73a2eed699 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:59 -0700
+Subject: xsk: validate metadata when processing requests
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 849b1664dbda1cf6c63e0fd4f9dec23782b8c851 ]
+
+The zero-copy path validates TX metadata while obtaining the descriptor
+context, then reads it again later when preparing the hardware request.
+User space can change the metadata between those operations and bypass the
+original validation.
+
+Validate the metadata in xsk_tx_metadata_request() and use the resulting
+flags snapshot for every feature check. Read request fields once so all
+zero-copy drivers process only values observed after successful
+validation.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-7-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igc/igc_main.c     |  2 +-
+ .../net/ethernet/mellanox/mlx5/core/en/xdp.c  |  5 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 +-
+ include/net/libeth/xsk.h                      |  2 +-
+ include/net/xdp_sock_drv.h                    | 51 ++++++++++---------
+ net/xdp/xsk_buff_pool.c                       |  6 +--
+ 6 files changed, 37 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index f69523e35ac10..99a414440bcaa 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -3082,7 +3082,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
+               meta_req.tx_buffer = bi;
+               meta_req.meta = meta;
+               meta_req.used_desc = 0;
+-              xsk_tx_metadata_request(&meta, &igc_xsk_tx_metadata_ops,
++              xsk_tx_metadata_request(pool, &meta, &igc_xsk_tx_metadata_ops,
+                                       &meta_req);
+               /* xsk_tx_metadata_request() may have updated next_to_use */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+index e467a7b067c7a..2f52e04b28de2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+@@ -504,7 +504,7 @@ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptx
+                */
+               mlx5e_xdp_mpwqe_session_start(sq);
+               if (meta)
+-                      xsk_tx_metadata_request(meta,
++                      xsk_tx_metadata_request(sq->xsk_pool, meta,
+                                               &mlx5e_xsk_tx_metadata_ops,
+                                               &session->wqe->eth);
+       }
+@@ -652,7 +652,8 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+       sq->pc += num_wqebbs;
+       if (meta)
+-              xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
++              xsk_tx_metadata_request(sq->xsk_pool, meta,
++                                      &mlx5e_xsk_tx_metadata_ops, eseg);
+       sq->doorbell_cseg = cseg;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 3380ce960de24..bca81ed28e073 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2574,8 +2574,8 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+               meta_req.set_ic = &set_ic;
+               meta_req.tbs = tx_q->tbs;
+               meta_req.edesc = &tx_q->dma_entx[entry];
+-              xsk_tx_metadata_request(&meta, &stmmac_xsk_tx_metadata_ops,
+-                                      &meta_req);
++              xsk_tx_metadata_request(pool, &meta,
++                                      &stmmac_xsk_tx_metadata_ops, &meta_req);
+               if (set_ic) {
+                       tx_q->tx_count_frames = 0;
+                       stmmac_set_tx_ic(priv, tx_desc);
+diff --git a/include/net/libeth/xsk.h b/include/net/libeth/xsk.h
+index 1a55daa32cf16..23eb240d5ba72 100644
+--- a/include/net/libeth/xsk.h
++++ b/include/net/libeth/xsk.h
+@@ -205,7 +205,7 @@ __libeth_xsk_xmit_fill_buf_md(const struct xdp_desc *xdesc,
+       BUILD_BUG_ON(!__builtin_constant_p(tmo == libeth_xsktmo));
+       tmo = tmo == libeth_xsktmo ? &__libeth_xsktmo : tmo;
+-      xsk_tx_metadata_request(&ctx.meta, tmo, &desc);
++      xsk_tx_metadata_request(sq->pool, &ctx.meta, tmo, &desc);
+       return desc;
+ }
+diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
+index 6d4f65b0ed53a..d74ca548d4d6a 100644
+--- a/include/net/xdp_sock_drv.h
++++ b/include/net/xdp_sock_drv.h
+@@ -241,7 +241,7 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
+  * details.
+  *
+  * Return: new &xdp_desc_ctx struct containing desc's DMA address and metadata
+- * pointer, if it is present and valid (initialized to %NULL otherwise).
++ * pointer, if it is present (initialized to %NULL otherwise).
+  */
+ static inline struct xdp_desc_ctx
+ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+@@ -270,54 +270,56 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+ /**
+  *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
+  *  and call appropriate xsk_tx_metadata_ops operation.
++ *  @pool: pointer to AF_XDP buffer pool, used to validate the metadata
+  *  @pmeta: pointer to pointer to AF_XDP metadata area
+  *  @ops: pointer to struct xsk_tx_metadata_ops
+- *  @priv: pointer to driver-private aread
++ *  @priv: pointer to driver-private area
+  *
+  *  This function should be called by the networking device when
+  *  it prepares AF_XDP egress packet.
+  */
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
++static inline void
++xsk_tx_metadata_request(const struct xsk_buff_pool *pool,
++                      struct xsk_tx_metadata **pmeta,
++                      const struct xsk_tx_metadata_ops *ops, void *priv)
+ {
+       const struct xsk_tx_metadata *meta = *pmeta;
++      u64 flags;
+       if (!meta)
+               return;
++      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags))) {
++              *pmeta = NULL;
++              return; /* no way to signal the error to the user */
++      }
++
+       if (ops->tmo_request_launch_time)
+-              if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+-                      ops->tmo_request_launch_time(meta->request.launch_time,
+-                                                   priv);
++              if (flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++                      ops->tmo_request_launch_time(
++                              READ_ONCE(meta->request.launch_time), priv);
+       if (ops->tmo_request_timestamp)
+-              if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
++              if (flags & XDP_TXMD_FLAGS_TIMESTAMP)
+                       ops->tmo_request_timestamp(priv);
+       if (ops->tmo_request_checksum)
+-              if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
+-                      ops->tmo_request_checksum(meta->request.csum_start,
+-                                                meta->request.csum_offset, priv);
++              if (flags & XDP_TXMD_FLAGS_CHECKSUM)
++                      ops->tmo_request_checksum(
++                              READ_ONCE(meta->request.csum_start),
++                              READ_ONCE(meta->request.csum_offset), priv);
+-      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++      if (!(flags & XDP_TXMD_FLAGS_TIMESTAMP))
+               *pmeta = NULL;
+ }
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+-      struct xsk_tx_metadata *meta;
+-      u64 flags;
+-
+       if (!pool->tx_metadata_len)
+               return NULL;
+-      meta = data - pool->tx_metadata_len;
+-      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
+-              return NULL; /* no way to signal the error to the user */
+-
+-      return meta;
++      return data - pool->tx_metadata_len;
+ }
+ static inline struct xsk_tx_metadata *
+@@ -516,9 +518,10 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+       return false;
+ }
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
++static inline void
++xsk_tx_metadata_request(const struct xsk_buff_pool *pool,
++                      struct xsk_tx_metadata **pmeta,
++                      const struct xsk_tx_metadata_ops *ops, void *priv)
+ {
+ }
+diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
+index c9688735b643c..772fe1838cfb3 100644
+--- a/net/xdp/xsk_buff_pool.c
++++ b/net/xdp/xsk_buff_pool.c
+@@ -769,11 +769,11 @@ EXPORT_SYMBOL(xp_raw_get_dma);
+  * @addr: desc address (from userspace)
+  *
+  * Helper for getting desc's DMA address and metadata pointer, if present.
+- * Saves one call on hotpath, double calculation of the actual address,
+- * and inline checks for metadata presence and sanity.
++ * Saves one call on hotpath and double calculation of the actual address.
++ * Metadata is validated later by xsk_tx_metadata_request().
+  *
+  * Return: new &xdp_desc_ctx struct containing desc's DMA address and metadata
+- * pointer, if it is present and valid (initialized to %NULL otherwise).
++ * pointer, if it is present (initialized to %NULL otherwise).
+  */
+ struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+ {
+-- 
+2.53.0
+
diff --git a/queue-6.6/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch b/queue-6.6/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
new file mode 100644 (file)
index 0000000..6906abf
--- /dev/null
@@ -0,0 +1,39 @@
+From 4c5e419746faf443d57a8f7d942011207af9192f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 14:57:22 -0700
+Subject: ARM: dts: BCM5301X: fix PCIe controller 2 second interrupt
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit bab4d538f8485e0d48538fcb82b285df3779278e ]
+
+PCIe controller 2 has interrupts 0-4 mapping to GIC SPI 138-142. The
+mapping for interrupt 1 was incorrectly set to 138 due to a copy-paste
+error. Fix it to 139.
+
+Assisted-by: opencode:big-pickle
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://lore.kernel.org/r/20260725215722.9323-1-rosenp@gmail.com
+Fixes: 3b3e35b279be ("ARM: dts: BCM5301X: Relicense AXI interrupts code to the GPL 2.0+ / MIT")
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/broadcom/bcm-ns.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+index 88fda18af1f8e..06acd72f9835a 100644
+--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
++++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+@@ -131,7 +131,7 @@ axi@18000000 {
+                       /* PCIe Controller 2 */
+                       <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+-                      <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
++                      <0x00014000 1 &gic GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+-- 
+2.53.0
+
diff --git a/queue-6.6/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-6.6/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..a5cb851
--- /dev/null
@@ -0,0 +1,50 @@
+From 164e8b22112f23dc119a8f72ab3bee69b2146793 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 41891d3aa1247..4c1fc9983746c 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -32,6 +32,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -60,6 +61,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch b/queue-6.6/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch
new file mode 100644 (file)
index 0000000..d856ef0
--- /dev/null
@@ -0,0 +1,45 @@
+From 32fe4d76959b548d832f3ad3415a25a4040de6f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 01:27:12 +0300
+Subject: arm64: dts: qcom: sdm850-lenovo-yoga-c630: lower PSCI cluster idle
+
+From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+
+[ Upstream commit 07db10de262f4150e24fd631a7a6c428f7bf80c9 ]
+
+With the default PSCI suspend value for cluster idle state Lenovo Yoga
+C630 isn't stable enough. For example it might reset if display device
+isn't probed early enough. Drop the bit 0x4000 from the PSCI suspend
+value to make C630 work in stable way. The bit was found by
+expertimenting with the cluster idle PSCI value. Most likely it results
+in the less deep sleep and more energy beign spent in the suspend state,
+but it's better than the non-stable system behaviour.
+
+Fixes: a1ade6cac5a2 ("arm64: dts: qcom: sdm845: Switch PSCI cpu idle states from PC to OSI")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260429-c630-fix-idle-v2-1-ac867dad6f21@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+index fe5c12da666e4..f757a02de7ab5 100644
+--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
++++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+@@ -347,6 +347,10 @@ &cdsp_pas {
+       status = "okay";
+ };
++&cluster_sleep_0 {
++      arm,psci-suspend-param = <0x41008244>;
++};
++
+ &gcc {
+       protected-clocks = <GCC_QSPI_CORE_CLK>,
+                          <GCC_QSPI_CORE_CLK_SRC>,
+-- 
+2.53.0
+
diff --git a/queue-6.6/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-6.6/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..11d73d1
--- /dev/null
@@ -0,0 +1,52 @@
+From d767bb78e56f0355095f01e8e284faa41c5bb594 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 93882e976ede4..2a5ce46af5a0a 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -264,6 +264,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -285,8 +286,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-6.6/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch b/queue-6.6/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
new file mode 100644 (file)
index 0000000..cf955ca
--- /dev/null
@@ -0,0 +1,57 @@
+From 68ad54d85e8926aed69e357bbdf3610c452e17ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:36 -0700
+Subject: bnxt_en: Disable EOP for TPA on all chips to prevent data corruption
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit c3faf548a00f4c17100cc9204746975fa46a73b9 ]
+
+EOP (End of frame padding) on the AGG ring may cause overlapping of
+zero padding at the end of one segment with the next segment's data.
+If Relaxed Ordering (RO) is enabled, the zero padding may overwrite
+valid data in the next segment and corrupt the data.  Older chips
+(P5 and older) do not automatically disable RO when EOP is enabled.
+On some ARM systems, data corruption was reported on 57508 (P5)
+chips with RO enabled.
+
+Always disable EOP on all chips on the AGG rings when TPA is enabled
+to fix the data corruption.
+
+Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 9fa9c634b9b27..e305b02b775e3 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3717,11 +3717,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+-              /* On P7, setting EOP will cause the chip to disable
+-               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
+-               * potentially higher performance with RO.
++              /* Disable EOP if TPA is enabled to prevent overlapping zero
++               * padding with the next segment's data.  On P7_PLUS, EOP will
++               * automatically disable Relaxed Ordering (RO) to prevent
++               * potential data corruption (and may degrade performance).  On
++               * older chips, RO will not be automatically disabled and may
++               * cause corruption.
+                */
+-              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++              if (!(bp->flags & BNXT_FLAG_TPA))
+                       type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+-- 
+2.53.0
+
diff --git a/queue-6.6/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch b/queue-6.6/bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
new file mode 100644 (file)
index 0000000..49f6303
--- /dev/null
@@ -0,0 +1,66 @@
+From 736828f51287f39241f06aaa0f3119db678b4b38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Nov 2025 13:56:46 -0800
+Subject: bnxt_en: Do not set EOP on RX AGG BDs on 5760X chips
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit 30f253f8d9a01d532fdb7ec6c8a9d4c15fe29241 ]
+
+With End-of-Packet padding (EOP) set, the chip will disable Relaxed
+Ordering (RO) of TPA data packets.  A TPA segment with EOP set will be
+padded to the next cache boundary and can potentially overwrite the
+beginning bytes of the next TPA segment when RO is enabled on 5760X.
+To prevent that, the chip disables RO for TPA when EOP is set.
+
+To take advantge of RO and higher performance, do not set EOP on
+5760X chips when TPA is enabled.  Define a proper RX_BD_FLAGS_AGG_EOP
+constant to make it clear that we are setting EOP.
+
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20251126215648.1885936-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: c3faf548a00f ("bnxt_en: Disable EOP for TPA on all chips to prevent data corruption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 ++++++++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index afe700575f530..9fa9c634b9b27 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3715,7 +3715,14 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+       if ((bp->flags & BNXT_FLAG_AGG_RINGS)) {
+               type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+-                      RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
++                      RX_BD_TYPE_RX_AGG_BD;
++
++              /* On P7, setting EOP will cause the chip to disable
++               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
++               * potentially higher performance with RO.
++               */
++              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++                      type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+       }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index bc1ff1085da7f..739ed9d0b5ab5 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -104,6 +104,7 @@ struct rx_bd {
+        #define RX_BD_TYPE_48B_BD_SIZE                          (2 << 4)
+        #define RX_BD_TYPE_64B_BD_SIZE                          (3 << 4)
+       #define RX_BD_FLAGS_SOP                                 (1 << 6)
++      #define RX_BD_FLAGS_AGG_EOP                             (1 << 6)
+       #define RX_BD_FLAGS_EOP                                 (1 << 7)
+       #define RX_BD_FLAGS_BUFFERS                             (3 << 8)
+        #define RX_BD_FLAGS_1_BUFFER_PACKET                     (0 << 8)
+-- 
+2.53.0
+
diff --git a/queue-6.6/bnxt_en-fix-ptp-pps-setting-bug.patch b/queue-6.6/bnxt_en-fix-ptp-pps-setting-bug.patch
new file mode 100644 (file)
index 0000000..bf85d95
--- /dev/null
@@ -0,0 +1,54 @@
+From 76a14183e5bc55749810fc18628fa351f389d6fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:37 -0700
+Subject: bnxt_en: Fix PTP PPS setting bug
+
+From: Keegan Freyhof <keegan.freyhof@broadcom.com>
+
+[ Upstream commit 80eaf88efec33ac77ed7726d066c4f2f932cc329 ]
+
+The existing driver logic is always turning on PTP_CLK_REQ_PPS
+regardless of the "on" parameter passed to bnxt_ptp_enable().
+During shutdown, PTP_CLK_REQ_PPS may be turned off and this
+bug will do the opposite and may trigger a PCIe PTM request TLP.
+On some systems this can trigger a PCIe AER.
+
+Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on"
+parameter.
+
+Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index 404b433f1bc08..d8f39776481b6 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -475,12 +475,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+               return rc;
+       case PTP_CLK_REQ_PPS:
+               /* Configure PHC PPS IN */
+-              rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
++              pin_id = 0;
++              if (!on)
++                      break;
++              rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+               if (rc)
+                       return rc;
+               rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
+               if (!rc)
+-                      ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
++                      ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL;
+               return rc;
+       default:
+               netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
+-- 
+2.53.0
+
diff --git a/queue-6.6/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-6.6/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..a8b33ef
--- /dev/null
@@ -0,0 +1,80 @@
+From c802dc61a0ad5325870acce50d36621ae334c949 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 7edf0fd58c346..ce6a3a0a2e153 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1535,8 +1535,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1598,9 +1598,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-6.6/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..4262284
--- /dev/null
@@ -0,0 +1,74 @@
+From 9e2aa98c292385d44b63b7726c7846dc17e68711 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 5e094c12fc94c..ad679bc42427c 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -12657,11 +12657,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               break;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
+@@ -12729,7 +12730,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -13588,8 +13589,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch b/queue-6.6/bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch
new file mode 100644 (file)
index 0000000..edad122
--- /dev/null
@@ -0,0 +1,240 @@
+From 0b22bcc51249d8fb83ee576a96ba6207e24619c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:09 -0700
+Subject: bpf: tcp: Avoid socket skips and repeats during iteration
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit f5080f612a1c587bf636bb23d2a2f4de276d60e4 ]
+
+Replace the offset-based approach for tracking progress through a bucket
+in the TCP table with one based on socket cookies. Remember the cookies
+of unprocessed sockets from the last batch and use this list to
+pick up where we left off or, in the case that the next socket
+disappears between reads, find the first socket after that point that
+still exists in the bucket and resume from there.
+
+This approach guarantees that all sockets that existed when iteration
+began and continue to exist throughout will be visited exactly once.
+Sockets that are added to the table during iteration may or may not be
+seen, but if they are they will be seen exactly once.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 147 ++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 115 insertions(+), 32 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index a826d137c86b4..e9f191315593c 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -58,6 +58,7 @@
+ #include <linux/times.h>
+ #include <linux/slab.h>
+ #include <linux/sched.h>
++#include <linux/sock_diag.h>
+ #include <net/net_namespace.h>
+ #include <net/icmp.h>
+@@ -2778,6 +2779,7 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ #ifdef CONFIG_BPF_SYSCALL
+ union bpf_tcp_iter_batch_item {
+       struct sock *sk;
++      __u64 cookie;
+ };
+ struct bpf_tcp_iter_state {
+@@ -2808,10 +2810,19 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
+ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ {
++      union bpf_tcp_iter_batch_item *item;
+       unsigned int cur_sk = iter->cur_sk;
++      __u64 cookie;
+-      while (cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[cur_sk++].sk);
++      /* Remember the cookies of the sockets we haven't seen yet, so we can
++       * pick up where we left off next time around.
++       */
++      while (cur_sk < iter->end_sk) {
++              item = &iter->batch[cur_sk++];
++              cookie = sock_gen_cookie(item->sk);
++              sock_gen_put(item->sk);
++              item->cookie = cookie;
++      }
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+@@ -2832,6 +2843,106 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+       return 0;
+ }
++static struct sock *bpf_iter_tcp_resume_bucket(struct sock *first_sk,
++                                             union bpf_tcp_iter_batch_item *cookies,
++                                             int n_cookies)
++{
++      struct hlist_nulls_node *node;
++      struct sock *sk;
++      int i;
++
++      for (i = 0; i < n_cookies; i++) {
++              sk = first_sk;
++              sk_nulls_for_each_from(sk, node)
++                      if (cookies[i].cookie == atomic64_read(&sk->sk_cookie))
++                              return sk;
++      }
++
++      return NULL;
++}
++
++static struct sock *bpf_iter_tcp_resume_listening(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      unsigned int find_cookie = iter->cur_sk;
++      unsigned int end_cookie = iter->end_sk;
++      int resume_bucket = st->bucket;
++      struct sock *sk;
++
++      if (end_cookie && find_cookie == end_cookie)
++              ++st->bucket;
++
++      sk = listening_get_first(seq);
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      if (sk && st->bucket == resume_bucket && end_cookie) {
++              sk = bpf_iter_tcp_resume_bucket(sk, &iter->batch[find_cookie],
++                                              end_cookie - find_cookie);
++              if (!sk) {
++                      spin_unlock(&hinfo->lhash2[st->bucket].lock);
++                      ++st->bucket;
++                      sk = listening_get_first(seq);
++              }
++      }
++
++      return sk;
++}
++
++static struct sock *bpf_iter_tcp_resume_established(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      unsigned int find_cookie = iter->cur_sk;
++      unsigned int end_cookie = iter->end_sk;
++      int resume_bucket = st->bucket;
++      struct sock *sk;
++
++      if (end_cookie && find_cookie == end_cookie)
++              ++st->bucket;
++
++      sk = established_get_first(seq);
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      if (sk && st->bucket == resume_bucket && end_cookie) {
++              sk = bpf_iter_tcp_resume_bucket(sk, &iter->batch[find_cookie],
++                                              end_cookie - find_cookie);
++              if (!sk) {
++                      spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
++                      ++st->bucket;
++                      sk = established_get_first(seq);
++              }
++      }
++
++      return sk;
++}
++
++static struct sock *bpf_iter_tcp_resume(struct seq_file *seq)
++{
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++      struct sock *sk = NULL;
++
++      switch (st->state) {
++      case TCP_SEQ_STATE_LISTENING:
++              sk = bpf_iter_tcp_resume_listening(seq);
++              if (sk)
++                      break;
++              st->bucket = 0;
++              st->state = TCP_SEQ_STATE_ESTABLISHED;
++              fallthrough;
++      case TCP_SEQ_STATE_ESTABLISHED:
++              sk = bpf_iter_tcp_resume_established(seq);
++              break;
++      }
++
++      return sk;
++}
++
+ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+                                                struct sock **start_sk)
+ {
+@@ -2916,32 +3027,12 @@ static void bpf_iter_tcp_unlock_bucket(struct seq_file *seq)
+ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       unsigned int expected;
+       struct sock *sk;
+       int err;
+-      /* The st->bucket is done.  Directly advance to the next
+-       * bucket instead of having the tcp_seek_last_pos() to skip
+-       * one by one in the current bucket and eventually find out
+-       * it has to advance to the next bucket.
+-       */
+-      if (iter->end_sk && iter->cur_sk == iter->end_sk) {
+-              st->offset = 0;
+-              st->bucket++;
+-              if (st->state == TCP_SEQ_STATE_LISTENING &&
+-                  st->bucket > hinfo->lhash2_mask) {
+-                      st->state = TCP_SEQ_STATE_ESTABLISHED;
+-                      st->bucket = 0;
+-              }
+-      }
+-
+-      iter->cur_sk = 0;
+-      iter->end_sk = 0;
+-
+-      sk = tcp_seek_last_pos(seq);
++      sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+@@ -2957,10 +3048,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       if (err)
+               return ERR_PTR(err);
+-      iter->cur_sk = 0;
+-      iter->end_sk = 0;
+-
+-      sk = tcp_seek_last_pos(seq);
++      sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+@@ -3012,11 +3100,6 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+                * meta.seq_num is used instead.
+                */
+               st->num++;
+-              /* Move st->offset to the next sk in the bucket such that
+-               * the future start() will resume at st->offset in
+-               * st->bucket.  See tcp_seek_last_pos().
+-               */
+-              st->offset++;
+               sock_gen_put(iter->batch[iter->cur_sk++].sk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch b/queue-6.6/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
new file mode 100644 (file)
index 0000000..41dcb58
--- /dev/null
@@ -0,0 +1,170 @@
+From 3d3c1423b616a0f7bd12a3f22bfb30af61e0b028 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:32:47 +0000
+Subject: bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()
+
+From: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+
+[ Upstream commit e5fd3f514e27db1f05fbd72ba615d74941e23c51 ]
+
+reqsk_queue_hash_req() publishes a TCP_NEW_SYN_RECV request_sock onto
+the ehash chain, drops the bucket lock, and only afterwards sets
+rsk_refcnt to 3.
+
+Lockless readers such as __inet_lookup_established() handle this with
+refcount_inc_not_zero(), but bpf_iter_tcp_established_batch() uses plain
+sock_hold() while holding the bucket lock, on the assumption that the
+lock guarantees sk_refcnt > 0. That assumption does not hold for
+request_sock:
+
+  CPU 0                                CPU 1
+  -----                                -----
+  tcp_conn_request()
+   reqsk_queue_hash_req()
+    inet_ehash_insert(req)
+     spin_lock(bucket)
+     __sk_nulls_add_node_rcu(req)      // rsk_refcnt == 0
+     spin_unlock(bucket)
+                                       bpf_iter_tcp_established_batch()
+                                        spin_lock(bucket)
+                                        sock_hold(req)   <-- addition on 0
+                                        spin_unlock(bucket)
+    refcount_set(&req->rsk_refcnt, 3)  // clobbers saturated value
+
+which surfaces as:
+
+  refcount_t: addition on 0; use-after-free.
+  WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x48/0x90, CPU#1
+  Call Trace:
+   bpf_iter_tcp_established_batch+0x14e/0x170
+   bpf_iter_tcp_batch+0x53/0x200
+   bpf_iter_tcp_seq_next+0x27/0x70
+   bpf_seq_read+0x107/0x410
+   vfs_read+0xb9/0x380
+
+The iterator's stolen reference is lost when the publishing CPU's
+refcount_set() overwrites the count, leaving the socket one reference
+short. When the last legitimate owner drops its reference the reqsk is
+freed while still reachable, leading to use-after-free.
+
+This reproduces in seconds with tcp_syncookies=0, a handful of threads
+doing connect()/close() to a local listener while others read an
+iter/tcp link in a tight loop.
+
+Use refcount_inc_not_zero() and skip the socket on failure. A skipped
+socket is still part of the bucket, so keep counting it in expected.
+The reallocations are sized from expected, and a request sock whose
+refcount gets published while the lock is held across the last realloc
+must already have room.
+
+A skipped socket is counted in expected but never batched, so end_sk
+can be short of expected on a batch that is actually complete. Decide
+completeness by whether the walk left any socket behind instead. The
+WARN after the locked realloc checks the same, replacing an
+end_sk == expected check that could not hold on that path since
+commit cdec67a489d4 ("bpf: tcp: Make sure iter->batch always
+contains a full bucket snapshot").
+
+If every matching socket in a bucket is mid-init (refcount 0), end_sk
+stays 0. Advance to the next bucket rather than returning a batch entry
+that was never filled this round.
+
+Fixes: 04c7820b776f ("bpf: tcp: Bpf iter batching and lock_sock")
+Assisted-by: Claude:unspecified
+Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://lore.kernel.org/bpf/20260730-bpf-iter-tcp-refcnt-v3-1-754b9c8a6717@linux.dev
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 43 ++++++++++++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 19 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index e9f191315593c..868a593d63ad2 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2977,24 +2977,24 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+ {
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct hlist_nulls_node *node;
+-      unsigned int expected = 1;
+-      struct sock *sk;
+-
+-      sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++].sk = *start_sk;
++      struct sock *sk = *start_sk;
++      unsigned int expected = 0;
+-      sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+-              if (seq_sk_match(seq, sk)) {
+-                      if (iter->end_sk < iter->max_sk) {
+-                              sock_hold(sk);
+-                              iter->batch[iter->end_sk++].sk = sk;
+-                      } else if (!*start_sk) {
+-                              /* Remember where we left off. */
+-                              *start_sk = sk;
+-                      }
+-                      expected++;
++              if (!seq_sk_match(seq, sk))
++                      continue;
++              expected++;
++              if (iter->end_sk < iter->max_sk) {
++                      /* reqsk_queue_hash_req() inserts with sk_refcnt == 0
++                       * and refcount_set()s it after the bucket lock drops.
++                       */
++                      if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
++                              continue;
++                      iter->batch[iter->end_sk++].sk = sk;
++              } else if (!*start_sk) {
++                      /* Remember where we left off. */
++                      *start_sk = sk;
+               }
+       }
+@@ -3032,12 +3032,13 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       struct sock *sk;
+       int err;
++again:
+       sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was too small. */
+@@ -3053,7 +3054,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was still too small. Hold onto the lock while we try
+@@ -3066,10 +3067,14 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return ERR_PTR(err);
+       }
+-      expected = bpf_iter_fill_batch(seq, &sk);
+-      WARN_ON_ONCE(iter->end_sk != expected);
++      bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(sk);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
++      if (unlikely(!iter->end_sk)) {
++              ++iter->state.bucket;
++              goto again;
++      }
+       return iter->batch[0].sk;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-tcp-get-rid-of-st_bucket_done.patch b/queue-6.6/bpf-tcp-get-rid-of-st_bucket_done.patch
new file mode 100644 (file)
index 0000000..6c52b38
--- /dev/null
@@ -0,0 +1,82 @@
+From 2f088a79af1ab9b612219e74a6b3453d8e71ec3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:07 -0700
+Subject: bpf: tcp: Get rid of st_bucket_done
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit e25ab9b874a4bd8c6e3e5ce66cbe8a1dd4096e2e ]
+
+Get rid of the st_bucket_done field to simplify TCP iterator state and
+logic. Before, st_bucket_done could be false if bpf_iter_tcp_batch
+returned a partial batch; however, with the last patch ("bpf: tcp: Make
+sure iter->batch always contains a full bucket snapshot"),
+st_bucket_done == true is equivalent to iter->cur_sk == iter->end_sk.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index d584ce27b2ddd..c32902c07bd0c 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2782,7 +2782,6 @@ struct bpf_tcp_iter_state {
+       unsigned int end_sk;
+       unsigned int max_sk;
+       struct sock **batch;
+-      bool st_bucket_done;
+ };
+ struct bpf_iter__tcp {
+@@ -2805,8 +2804,10 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
+ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ {
+-      while (iter->cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[iter->cur_sk++]);
++      unsigned int cur_sk = iter->cur_sk;
++
++      while (cur_sk < iter->end_sk)
++              sock_gen_put(iter->batch[cur_sk++]);
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+@@ -2923,7 +2924,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+        * one by one in the current bucket and eventually find out
+        * it has to advance to the next bucket.
+        */
+-      if (iter->st_bucket_done) {
++      if (iter->end_sk && iter->cur_sk == iter->end_sk) {
+               st->offset = 0;
+               st->bucket++;
+               if (st->state == TCP_SEQ_STATE_LISTENING &&
+@@ -2935,7 +2936,6 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       iter->cur_sk = 0;
+       iter->end_sk = 0;
+-      iter->st_bucket_done = true;
+       sk = tcp_seek_last_pos(seq);
+       if (!sk)
+@@ -3083,10 +3083,8 @@ static void bpf_iter_tcp_seq_stop(struct seq_file *seq, void *v)
+                       (void)tcp_prog_seq_show(prog, &meta, v, 0);
+       }
+-      if (iter->cur_sk < iter->end_sk) {
++      if (iter->cur_sk < iter->end_sk)
+               bpf_iter_tcp_put_batch(iter);
+-              iter->st_bucket_done = false;
+-      }
+ }
+ static const struct seq_operations bpf_iter_tcp_seq_ops = {
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch b/queue-6.6/bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch
new file mode 100644 (file)
index 0000000..88c9021
--- /dev/null
@@ -0,0 +1,64 @@
+From d92dd047190ae8e558cd84d7836e5352bebb3da0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:05 -0700
+Subject: bpf: tcp: Make mem flags configurable through
+ bpf_iter_tcp_realloc_batch
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit 8271bec9fc1cfe522b1a18cacbefd6712a3d41c2 ]
+
+Prepare for the next patch which needs to be able to choose either
+GFP_USER or GFP_NOWAIT for calls to bpf_iter_tcp_realloc_batch.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index c8d35f1c0ece2..17bd4e3b4558d 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2810,12 +2810,12 @@ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+-                                    unsigned int new_batch_sz)
++                                    unsigned int new_batch_sz, gfp_t flags)
+ {
+       struct sock **new_batch;
+       new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
+-                           GFP_USER | __GFP_NOWARN);
++                           flags | __GFP_NOWARN);
+       if (!new_batch)
+               return -ENOMEM;
+@@ -2927,7 +2927,8 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return sk;
+       }
+-      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2)) {
++      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
++                                                  GFP_USER)) {
+               resized = true;
+               goto again;
+       }
+@@ -3355,7 +3356,7 @@ static int bpf_iter_init_tcp(void *priv_data, struct bpf_iter_aux_info *aux)
+       if (err)
+               return err;
+-      err = bpf_iter_tcp_realloc_batch(iter, INIT_BATCH_SZ);
++      err = bpf_iter_tcp_realloc_batch(iter, INIT_BATCH_SZ, GFP_USER);
+       if (err) {
+               bpf_iter_fini_seq_net(priv_data);
+               return err;
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch b/queue-6.6/bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch
new file mode 100644 (file)
index 0000000..c6b7749
--- /dev/null
@@ -0,0 +1,257 @@
+From b714bf7dc84a132dad0ed1c4341ca76bdb6436e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:06 -0700
+Subject: bpf: tcp: Make sure iter->batch always contains a full bucket
+ snapshot
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit cdec67a489d4fdae3e83e04fca0419136a83c4c2 ]
+
+Require that iter->batch always contains a full bucket snapshot. This
+invariant is important to avoid skipping or repeating sockets during
+iteration when combined with the next few patches. Before, there were
+two cases where a call to bpf_iter_tcp_batch may only capture part of a
+bucket:
+
+1. When bpf_iter_tcp_realloc_batch() returns -ENOMEM.
+2. When more sockets are added to the bucket while calling
+   bpf_iter_tcp_realloc_batch(), making the updated batch size
+   insufficient.
+
+In cases where the batch size only covers part of a bucket, it is
+possible to forget which sockets were already visited, especially if we
+have to process a bucket in more than two batches. This forces us to
+choose between repeating or skipping sockets, so don't allow this:
+
+1. Stop iteration and propagate -ENOMEM up to userspace if reallocation
+   fails instead of continuing with a partial batch.
+2. Try bpf_iter_tcp_realloc_batch() with GFP_USER just as before, but if
+   we still aren't able to capture the full bucket, call
+   bpf_iter_tcp_realloc_batch() again while holding the bucket lock to
+   guarantee the bucket does not change. On the second attempt use
+   GFP_NOWAIT since we hold onto the spin lock.
+
+I did some manual testing to exercise the code paths where GFP_NOWAIT is
+used and where ERR_PTR(err) is returned. I used the realloc test cases
+included later in this series to trigger a scenario where a realloc
+happens inside bpf_iter_tcp_batch and made a small code tweak to force
+the first realloc attempt to allocate a too-small batch, thus requiring
+another attempt with GFP_NOWAIT. Some printks showed both reallocs with
+the tests passing:
+
+Jun 27 00:00:53 crow kernel: again GFP_USER
+Jun 27 00:00:53 crow kernel: again GFP_NOWAIT
+Jun 27 00:00:53 crow kernel: again GFP_USER
+Jun 27 00:00:53 crow kernel: again GFP_NOWAIT
+
+With this setup, I also forced each of the bpf_iter_tcp_realloc_batch
+calls to return -ENOMEM to ensure that iteration ends and that the
+read() in userspace fails.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 109 +++++++++++++++++++++++++++++++-------------
+ 1 file changed, 77 insertions(+), 32 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 17bd4e3b4558d..d584ce27b2ddd 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2819,7 +2819,7 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+       if (!new_batch)
+               return -ENOMEM;
+-      bpf_iter_tcp_put_batch(iter);
++      memcpy(new_batch, iter->batch, sizeof(*iter->batch) * iter->end_sk);
+       kvfree(iter->batch);
+       iter->batch = new_batch;
+       iter->max_sk = new_batch_sz;
+@@ -2828,69 +2828,95 @@ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+ }
+ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+-                                               struct sock *start_sk)
++                                               struct sock **start_sk)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       struct hlist_nulls_node *node;
+       unsigned int expected = 1;
+       struct sock *sk;
+-      sock_hold(start_sk);
+-      iter->batch[iter->end_sk++] = start_sk;
++      sock_hold(*start_sk);
++      iter->batch[iter->end_sk++] = *start_sk;
+-      sk = sk_nulls_next(start_sk);
++      sk = sk_nulls_next(*start_sk);
++      *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+                               iter->batch[iter->end_sk++] = sk;
++                      } else if (!*start_sk) {
++                              /* Remember where we left off. */
++                              *start_sk = sk;
+                       }
+                       expected++;
+               }
+       }
+-      spin_unlock(&hinfo->lhash2[st->bucket].lock);
+       return expected;
+ }
+ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+-                                                 struct sock *start_sk)
++                                                 struct sock **start_sk)
+ {
+-      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+-      struct tcp_iter_state *st = &iter->state;
+       struct hlist_nulls_node *node;
+       unsigned int expected = 1;
+       struct sock *sk;
+-      sock_hold(start_sk);
+-      iter->batch[iter->end_sk++] = start_sk;
++      sock_hold(*start_sk);
++      iter->batch[iter->end_sk++] = *start_sk;
+-      sk = sk_nulls_next(start_sk);
++      sk = sk_nulls_next(*start_sk);
++      *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+                               iter->batch[iter->end_sk++] = sk;
++                      } else if (!*start_sk) {
++                              /* Remember where we left off. */
++                              *start_sk = sk;
+                       }
+                       expected++;
+               }
+       }
+-      spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
+       return expected;
+ }
++static unsigned int bpf_iter_fill_batch(struct seq_file *seq,
++                                      struct sock **start_sk)
++{
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++
++      if (st->state == TCP_SEQ_STATE_LISTENING)
++              return bpf_iter_tcp_listening_batch(seq, start_sk);
++      else
++              return bpf_iter_tcp_established_batch(seq, start_sk);
++}
++
++static void bpf_iter_tcp_unlock_bucket(struct seq_file *seq)
++{
++      struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
++      struct bpf_tcp_iter_state *iter = seq->private;
++      struct tcp_iter_state *st = &iter->state;
++
++      if (st->state == TCP_SEQ_STATE_LISTENING)
++              spin_unlock(&hinfo->lhash2[st->bucket].lock);
++      else
++              spin_unlock_bh(inet_ehash_lockp(hinfo, st->bucket));
++}
++
+ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+ {
+       struct inet_hashinfo *hinfo = seq_file_net(seq)->ipv4.tcp_death_row.hashinfo;
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct tcp_iter_state *st = &iter->state;
+       unsigned int expected;
+-      bool resized = false;
+       struct sock *sk;
++      int err;
+       /* The st->bucket is done.  Directly advance to the next
+        * bucket instead of having the tcp_seek_last_pos() to skip
+@@ -2907,33 +2933,52 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               }
+       }
+-again:
+-      /* Get a new batch */
+       iter->cur_sk = 0;
+       iter->end_sk = 0;
+-      iter->st_bucket_done = false;
++      iter->st_bucket_done = true;
+       sk = tcp_seek_last_pos(seq);
+       if (!sk)
+               return NULL; /* Done */
+-      if (st->state == TCP_SEQ_STATE_LISTENING)
+-              expected = bpf_iter_tcp_listening_batch(seq, sk);
+-      else
+-              expected = bpf_iter_tcp_established_batch(seq, sk);
++      expected = bpf_iter_fill_batch(seq, &sk);
++      if (likely(iter->end_sk == expected))
++              goto done;
+-      if (iter->end_sk == expected) {
+-              iter->st_bucket_done = true;
+-              return sk;
+-      }
++      /* Batch size was too small. */
++      bpf_iter_tcp_unlock_bucket(seq);
++      bpf_iter_tcp_put_batch(iter);
++      err = bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
++                                       GFP_USER);
++      if (err)
++              return ERR_PTR(err);
++
++      iter->cur_sk = 0;
++      iter->end_sk = 0;
++
++      sk = tcp_seek_last_pos(seq);
++      if (!sk)
++              return NULL; /* Done */
++
++      expected = bpf_iter_fill_batch(seq, &sk);
++      if (likely(iter->end_sk == expected))
++              goto done;
+-      if (!resized && !bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2,
+-                                                  GFP_USER)) {
+-              resized = true;
+-              goto again;
++      /* Batch size was still too small. Hold onto the lock while we try
++       * again with a larger batch to make sure the current bucket's size
++       * does not change in the meantime.
++       */
++      err = bpf_iter_tcp_realloc_batch(iter, expected, GFP_NOWAIT);
++      if (err) {
++              bpf_iter_tcp_unlock_bucket(seq);
++              return ERR_PTR(err);
+       }
+-      return sk;
++      expected = bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(iter->end_sk != expected);
++done:
++      bpf_iter_tcp_unlock_bucket(seq);
++      return iter->batch[0];
+ }
+ static void *bpf_iter_tcp_seq_start(struct seq_file *seq, loff_t *pos)
+-- 
+2.53.0
+
diff --git a/queue-6.6/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch b/queue-6.6/bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch
new file mode 100644 (file)
index 0000000..f0044bf
--- /dev/null
@@ -0,0 +1,124 @@
+From 63374aa7d62904b8b764d2ab6ca4851df4b2e69a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jul 2025 11:09:08 -0700
+Subject: bpf: tcp: Use bpf_tcp_iter_batch_item for bpf_tcp_iter_state batch
+ items
+
+From: Jordan Rife <jordan@jrife.io>
+
+[ Upstream commit efeb820951ebf3778830256496ff72d00d135310 ]
+
+Prepare for the next patch that tracks cookies between iterations by
+converting struct sock **batch to union bpf_tcp_iter_batch_item *batch
+inside struct bpf_tcp_iter_state.
+
+Signed-off-by: Jordan Rife <jordan@jrife.io>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Stable-dep-of: e5fd3f514e27 ("bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index c32902c07bd0c..a826d137c86b4 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2776,12 +2776,16 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ }
+ #ifdef CONFIG_BPF_SYSCALL
++union bpf_tcp_iter_batch_item {
++      struct sock *sk;
++};
++
+ struct bpf_tcp_iter_state {
+       struct tcp_iter_state state;
+       unsigned int cur_sk;
+       unsigned int end_sk;
+       unsigned int max_sk;
+-      struct sock **batch;
++      union bpf_tcp_iter_batch_item *batch;
+ };
+ struct bpf_iter__tcp {
+@@ -2807,13 +2811,13 @@ static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
+       unsigned int cur_sk = iter->cur_sk;
+       while (cur_sk < iter->end_sk)
+-              sock_gen_put(iter->batch[cur_sk++]);
++              sock_gen_put(iter->batch[cur_sk++].sk);
+ }
+ static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
+                                     unsigned int new_batch_sz, gfp_t flags)
+ {
+-      struct sock **new_batch;
++      union bpf_tcp_iter_batch_item *new_batch;
+       new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
+                            flags | __GFP_NOWARN);
+@@ -2837,7 +2841,7 @@ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+       struct sock *sk;
+       sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++] = *start_sk;
++      iter->batch[iter->end_sk++].sk = *start_sk;
+       sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+@@ -2845,7 +2849,7 @@ static unsigned int bpf_iter_tcp_listening_batch(struct seq_file *seq,
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+-                              iter->batch[iter->end_sk++] = sk;
++                              iter->batch[iter->end_sk++].sk = sk;
+                       } else if (!*start_sk) {
+                               /* Remember where we left off. */
+                               *start_sk = sk;
+@@ -2866,7 +2870,7 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+       struct sock *sk;
+       sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++] = *start_sk;
++      iter->batch[iter->end_sk++].sk = *start_sk;
+       sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+@@ -2874,7 +2878,7 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+               if (seq_sk_match(seq, sk)) {
+                       if (iter->end_sk < iter->max_sk) {
+                               sock_hold(sk);
+-                              iter->batch[iter->end_sk++] = sk;
++                              iter->batch[iter->end_sk++].sk = sk;
+                       } else if (!*start_sk) {
+                               /* Remember where we left off. */
+                               *start_sk = sk;
+@@ -2978,7 +2982,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       WARN_ON_ONCE(iter->end_sk != expected);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
+-      return iter->batch[0];
++      return iter->batch[0].sk;
+ }
+ static void *bpf_iter_tcp_seq_start(struct seq_file *seq, loff_t *pos)
+@@ -3013,11 +3017,11 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+                * st->bucket.  See tcp_seek_last_pos().
+                */
+               st->offset++;
+-              sock_gen_put(iter->batch[iter->cur_sk++]);
++              sock_gen_put(iter->batch[iter->cur_sk++].sk);
+       }
+       if (iter->cur_sk < iter->end_sk)
+-              sk = iter->batch[iter->cur_sk];
++              sk = iter->batch[iter->cur_sk].sk;
+       else
+               sk = bpf_iter_tcp_batch(seq);
+-- 
+2.53.0
+
diff --git a/queue-6.6/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch b/queue-6.6/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
new file mode 100644 (file)
index 0000000..070fcfd
--- /dev/null
@@ -0,0 +1,96 @@
+From c3fa879a175b1840b27fee7750f538d9a4accd97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 14:53:52 +0300
+Subject: btrfs: fix memory leak in btrfs_do_encoded_write()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit d2a4e4e626b2f4670b69b430c357f03f53eb6632 ]
+
+Local fuzzing of 6.12.94 has found the following memory leak:
+
+Unreferenced object 0xffff888018050a80 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 10 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
+    10 0a 05 18 80 88 ff ff 10 0a 05 18 80 88 ff ff  ................
+  backtrace (crc a8a6fc29):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    extent_changeset_alloc fs/btrfs/extent_io.h:207 [inline]
+    qgroup_reserve_data+0x1c5/0x7d0 fs/btrfs/qgroup.c:4305
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Unreferenced object 0xffff888018050a00 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 ff 0f 00 00 00 00 00 00  ................
+    90 0a 05 18 80 88 ff ff 90 0a 05 18 80 88 ff ff  ................
+  backtrace (crc cb5c9580):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    kzalloc_noprof include/linux/slab.h:1014 [inline]
+    ulist_prealloc+0x9c/0x110 fs/btrfs/ulist.c:114
+    extent_changeset_prealloc fs/btrfs/extent_io.h:217 [inline]
+    __set_extent_bit+0x16b/0x1a70 fs/btrfs/extent-io-tree.c:1086
+    set_record_extent_bits+0x50/0x90 fs/btrfs/extent-io-tree.c:1821
+    qgroup_reserve_data+0x274/0x7d0 fs/btrfs/qgroup.c:4312
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fix this by freeing an extent changeset before returning from
+btrfs_do_encoded_write().
+
+Fixes: 7c0c7269f7b5 ("btrfs: add BTRFS_IOC_ENCODED_WRITE")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index b1e2b3f732cce..e843531201bef 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -10640,6 +10640,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
+       }
+       kvfree(pages);
+ out:
++      extent_changeset_free(data_reserved);
+       if (ret >= 0)
+               iocb->ki_pos += encoded->len;
+       return ret;
+-- 
+2.53.0
+
diff --git a/queue-6.6/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-6.6/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..8740658
--- /dev/null
@@ -0,0 +1,70 @@
+From 51898a436ab6cf9ba19ddda9629df0d74d5ec913 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 461f57f66631c..fbd1afe178a36 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -309,7 +309,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
+@@ -343,7 +343,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-6.6/devlink-fix-net-namespace-reference-leak-in-reload.patch b/queue-6.6/devlink-fix-net-namespace-reference-leak-in-reload.patch
new file mode 100644 (file)
index 0000000..60baf7e
--- /dev/null
@@ -0,0 +1,42 @@
+From 2eff8e639193246e92867212442c17878c78fc13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:06:00 +0300
+Subject: devlink: fix net namespace reference leak in reload
+
+From: Or Har-Toov <ohartoov@nvidia.com>
+
+[ Upstream commit 1c4dac9bf1d2ac31da63b794bdec697777cbd0fd ]
+
+devlink_nl_reload_doit() calls devlink_netns_get(), which returns a net
+with a held reference. When the requested namespace differs from the
+current one and the reload action is not DRIVER_REINIT, the function
+returns -EOPNOTSUPP without releasing the reference. Add the missing
+put_net() on this error path.
+
+Fixes: 2edd92570441 ("devlink: don't allow to change net namespace for FW_ACTIVATE reload action")
+Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260729080600.2427721-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/dev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/devlink/dev.c b/net/devlink/dev.c
+index bba4ace7d22ba..c70d4dc599b85 100644
+--- a/net/devlink/dev.c
++++ b/net/devlink/dev.c
+@@ -505,6 +505,7 @@ int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
+                   action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Changing namespace is only supported for reinit action");
++                      put_net(dest_net);
+                       return -EOPNOTSUPP;
+               }
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.6/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch b/queue-6.6/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
new file mode 100644 (file)
index 0000000..165f532
--- /dev/null
@@ -0,0 +1,79 @@
+From 5ef9c8edfca2171a6af04795098a2e9006e3622b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:38:06 +0800
+Subject: drm/bridge: ps8640: propagate AUX transfer register errors
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 20697ecb299cd77b4cf8b28f655e56606b0472d8 ]
+
+ps8640_aux_transfer_msg() programs the AUX address registers, starts the
+AUX transfer, waits for SWAUX_SEND to clear, and reads the AUX status
+register. Several of those regmap operations have return values, but the
+function only checks a stale ret after the status read.
+
+Propagate failures from the address write, transfer start, completion
+poll, and status read. This avoids returning a transfer length when the
+bridge register transaction or AUX completion wait failed.
+
+Fixes: 13afcdd7277e ("drm/bridge: parade-ps8640: Add support for AUX channel")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patch.msgid.link/20260723103509.2-ps8640-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/parade-ps8640.c | 27 ++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
+index 14d4dcf239da8..61ea855e55d87 100644
+--- a/drivers/gpu/drm/bridge/parade-ps8640.c
++++ b/drivers/gpu/drm/bridge/parade-ps8640.c
+@@ -258,8 +258,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+       addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD :
+                                             ((len - 1) & SWAUX_LENGTH_MASK);
+-      regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
+-                        ARRAY_SIZE(addr_len));
++      ret = regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
++                              ARRAY_SIZE(addr_len));
++      if (ret) {
++              DRM_DEV_ERROR(dev,
++                            "failed to write AUX address %#x, len %zu: %d\n",
++                            msg->address, len, ret);
++              return ret;
++      }
+       if (len && (request == DP_AUX_NATIVE_WRITE ||
+                   request == DP_AUX_I2C_WRITE)) {
+@@ -275,13 +281,22 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+               }
+       }
+-      regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      ret = regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to start AUX transfer: %d\n", ret);
++              return ret;
++      }
+       /* Zero delay loop because i2c transactions are slow already */
+-      regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
+-                               !(data & SWAUX_SEND), 0, 50 * 1000);
++      ret = regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
++                                     !(data & SWAUX_SEND), 0, 50 * 1000);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to complete AUX transfer: %d\n",
++                            ret);
++              return ret;
++      }
+-      regmap_read(map, PAGE0_SWAUX_STATUS, &data);
++      ret = regmap_read(map, PAGE0_SWAUX_STATUS, &data);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n",
+                             ret);
+-- 
+2.53.0
+
diff --git a/queue-6.6/hwmon-ads7828-fix-external-vref-regulator-handling.patch b/queue-6.6/hwmon-ads7828-fix-external-vref-regulator-handling.patch
new file mode 100644 (file)
index 0000000..7e03878
--- /dev/null
@@ -0,0 +1,71 @@
+From 5d033fcd110374088eeeb3fcbc4b1dfbaf9b513f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 14:16:45 +0800
+Subject: hwmon: (ads7828) Fix external VREF regulator handling
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit fddb5ceaf901b050ed2a1a7deeecbf97e003435a ]
+
+The driver currently has two issues with the external VREF regulator
+handling in ads7828_probe():
+
+1. All errors from devm_regulator_get_optional() are ignored, causing the
+   driver to incorrectly fall back to internal VREF even for transient
+   errors like -EPROBE_DEFER or genuine failures like -ENOMEM.
+
+2. The external regulator is never enabled. The driver calls
+   regulator_get_voltage() without first calling regulator_enable(),
+   so the VREF pin may remain unpowered if the regulator is not
+   configured as always-on.
+
+Fix both issues by switching to devm_regulator_get_enable_read_voltage(),
+which handles regulator get, enable, and voltage read in one call.
+Only -ENODEV (no regulator specified in device tree) should trigger the
+fallback to internal VREF. All other errors are propagated to the caller.
+
+Fixes: a8ddfea09566 ("hwmon: (ads7828) Accept optional parameters from device tree")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260805061645.1331652-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ads7828.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
+index 809e830f52a6b..b9ed146a24cc1 100644
+--- a/drivers/hwmon/ads7828.c
++++ b/drivers/hwmon/ads7828.c
+@@ -108,12 +108,11 @@ static int ads7828_probe(struct i2c_client *client)
+       struct ads7828_data *data;
+       struct device *hwmon_dev;
+       unsigned int vref_mv = ADS7828_INT_VREF_MV;
+-      unsigned int vref_uv;
++      int vref_uv;
+       bool diff_input = false;
+       bool ext_vref = false;
+       unsigned int regval;
+       enum ads7828_chips chip;
+-      struct regulator *reg;
+       data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
+       if (!data)
+@@ -127,9 +126,11 @@ static int ads7828_probe(struct i2c_client *client)
+       } else if (dev->of_node) {
+               diff_input = of_property_read_bool(dev->of_node,
+                                                  "ti,differential-input");
+-              reg = devm_regulator_get_optional(dev, "vref");
+-              if (!IS_ERR(reg)) {
+-                      vref_uv = regulator_get_voltage(reg);
++              vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref");
++              if (vref_uv < 0) {
++                      if (vref_uv != -ENODEV)
++                              return vref_uv;
++              } else {
+                       vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
+                       if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
+                           vref_mv > ADS7828_EXT_VREF_MV_MAX)
+-- 
+2.53.0
+
diff --git a/queue-6.6/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch b/queue-6.6/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
new file mode 100644 (file)
index 0000000..3347da1
--- /dev/null
@@ -0,0 +1,50 @@
+From 5424e4121c1d38280f8b0800cde1bad04dedb30d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 07:19:20 +0000
+Subject: hwmon: (corsair-psu) fix possible out-of-bounds access on missing
+ string termination
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit 36c4d73ce05d1d8896c2669eb0730d35a02a2ec1 ]
+
+In theory it could be possible that the REPLY_SIZE sized buffers for
+holding the vendor and product strings could be end up missing the null
+termination (for example by malicious hardware built on purpose)
+required by the seq_printf() call. That limits the debugfs printf calls
+to a maximum string length of REPLY_SIZE.
+
+Fixes: d115b51e0e567 ("hwmon: add Corsair PSU HID controller driver")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/anLj9gPWRoRDbQBV@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 4ab73bcef1d12..61d1b22bc63ec 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -709,7 +709,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->vendor);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
+       return 0;
+ }
+@@ -719,7 +719,7 @@ static int product_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->product);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/hwmon-lm25066-use-i2c_get_match_data.patch b/queue-6.6/hwmon-lm25066-use-i2c_get_match_data.patch
new file mode 100644 (file)
index 0000000..b6f5dc9
--- /dev/null
@@ -0,0 +1,71 @@
+From 69369d1e3a5e2d2a3799d97ea3b33fee5757e0df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Nov 2023 14:57:02 -0600
+Subject: hwmon: (lm25066) Use i2c_get_match_data()
+
+From: Rob Herring <robh@kernel.org>
+
+[ Upstream commit ac0c26bae662138eac9b49215e505b402f7e80e3 ]
+
+Use preferred i2c_get_match_data() instead of of_match_device() and
+i2c_match_id() to get the driver match data. With this, adjust the
+includes to explicitly include the correct headers.
+
+Adjust the 'chips' enum to not use 0, so that no match data can be
+distinguished from a valid enum value.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20231115205703.3730448-3-robh@kernel.org
+[groeck: Use double cast for enum chips assignment to make compiler happy]
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Stable-dep-of: 0dabe8a56f77 ("hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index 929fa6d34efdc..3a20df5a43ec8 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,10 +14,10 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
+-#include <linux/of_device.h>
++#include <linux/of.h>
+ #include "pmbus.h"
+-enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
++enum chips { lm25056 = 1, lm25066, lm5064, lm5066, lm5066i };
+ #define LM25066_READ_VAUX             0xd0
+ #define LM25066_MFR_READ_IIN          0xd1
+@@ -468,8 +468,6 @@ static int lm25066_probe(struct i2c_client *client)
+       struct lm25066_data *data;
+       struct pmbus_driver_info *info;
+       const struct __coeff *coeff;
+-      const struct of_device_id *of_id;
+-      const struct i2c_device_id *i2c_id;
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_READ_BYTE_DATA))
+@@ -484,14 +482,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (config < 0)
+               return config;
+-      i2c_id = i2c_match_id(lm25066_id, client);
++      data->id = (enum chips)(unsigned long)i2c_get_match_data(client);
+-      of_id = of_match_device(lm25066_of_match, &client->dev);
+-      if (of_id && (unsigned long)of_id->data != i2c_id->driver_data)
+-              dev_notice(&client->dev, "Device mismatch: %s in device tree, %s detected\n",
+-                         of_id->name, i2c_id->name);
+-
+-      data->id = i2c_id->driver_data;
+       info = &data->info;
+       info->pages = 1;
+-- 
+2.53.0
+
diff --git a/queue-6.6/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch b/queue-6.6/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
new file mode 100644 (file)
index 0000000..ebd09b5
--- /dev/null
@@ -0,0 +1,57 @@
+From 0bd3bc90edec78af41cfba197a5b49b646c8366d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:48:42 +0800
+Subject: hwmon: (nzxt-smart2) Check return value of init_device() in probe
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit d533882ce1060866a590257f2c77ee23eabef5b8 ]
+
+The init_device() call in nzxt_smart2_hid_probe() can fail because it
+sends HID output reports to the hardware to detect fans and set the
+update interval.  If the hardware is not responding or the HID reports
+fail, init_device() returns a negative error code.
+
+However, the return value was ignored, causing the probe to continue
+and register an hwmon device even though the device was never properly
+initialized.  This leads to an inconsistent state where the driver
+reports stale data or blocks on wait queues that will never be woken.
+
+The same function's return value is already checked in the
+reset_resume() handler, confirming the author's intent that errors
+should be propagated.
+
+Note that this fix was not possible before commit 59d104b54b0b
+("hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop")
+because the out_hw_close error path was missing hid_device_io_stop(),
+which would have opened a use-after-free risk window.
+
+Fixes: 53e68c20aeb1 ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2.")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260804074842.505923-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/nzxt-smart2.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
+index 5bbe6f3f8af48..00c8d3bc3e344 100644
+--- a/drivers/hwmon/nzxt-smart2.c
++++ b/drivers/hwmon/nzxt-smart2.c
+@@ -760,7 +760,11 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
+       hid_device_io_start(hdev);
+-      init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      ret = init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      if (ret) {
++              dev_err(&hdev->dev, "init_device failed: %d\n", ret);
++              goto out_hw_close;
++      }
+       drvdata->hwmon =
+               hwmon_device_register_with_info(&hdev->dev, "nzxtsmart2", drvdata,
+-- 
+2.53.0
+
diff --git a/queue-6.6/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch b/queue-6.6/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
new file mode 100644 (file)
index 0000000..3fecba0
--- /dev/null
@@ -0,0 +1,71 @@
+From d9116982a429a72f0adbe1fe596b56a601467165 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 14:12:31 -0700
+Subject: hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 0dabe8a56f772f0ece46d2597799f412c277d874 ]
+
+In lm25066_probe(), the PMBus coefficients for current and power are
+scaled based on the shunt resistor value. The calculation evaluates the
+multiplication using 32-bit arithmetic because info->m is an int and
+shunt is a u32:
+
+static int lm25066_probe(struct i2c_client *client) {
+    ...
+    info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+    info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
+    ...
+}
+
+For large coefficients like 26882 (LM25056) or 15076 (LM5066i), a device
+tree shunt-resistor-micro-ohms value exceeding approximately 159,000
+(159 mOhm, which is physically valid for low-current applications) causes
+the intermediate product to exceed UINT_MAX (4,294,967,295). This results
+in a silent wraparound before the division by 1000.
+
+Furthermore, if the wrapped value has the most significant bit set,
+converting it back to the signed int info->m results in negative
+coefficients. This logic error leads to drastically corrupted current and
+power readings, which can cause erratic thermal or power management
+behavior in the system.
+
+Fix the problem by using 64-bit operations for the multiply/divide
+operations. This can still overflow, but only for unreasonably large
+shunt resistor values.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: 94ee5fcc240fe ("hwmon: (pmbus/lm25066) Support configurable sense resistor values")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index 3a20df5a43ec8..8a94c4cfb5d19 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
++#include <linux/math.h>
+ #include <linux/of.h>
+ #include "pmbus.h"
+@@ -540,8 +541,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
+               shunt = 1000;
+-      info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+-      info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
++      info->m[PSC_CURRENT_IN] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_CURRENT_IN] * shunt, 1000);
++      info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_POWER] * shunt, 1000);
+ #if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)
+       /* LM25056 doesn't support OPERATION */
+-- 
+2.53.0
+
diff --git a/queue-6.6/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch b/queue-6.6/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
new file mode 100644 (file)
index 0000000..6a95690
--- /dev/null
@@ -0,0 +1,259 @@
+From e74bd05e1da1fbd8de57594226d1a3cfd7bcdabc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:05 +0300
+Subject: ipvs: avoid out-of-bounds write in ip_vs_nat_icmp
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 646922a0379496154e8c8faca4f8e2fd9100cacc ]
+
+Sashiko warns that local attacker can modify the packet
+while it is processed by IPVS. Some places read the
+IP ihl field multiple times which can cause out-of-bounds
+access. One such place is ip_vs_nat_icmp where we
+can write after the validated area.
+
+Fix it by providing ciph argument just like it is done for
+IPv6 and use ciph->len as offset to the embedded transport
+header.
+
+Modify some IPv4 header checks by reading the ihl field
+only once.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://sashiko.dev/#/patchset/20260722101517.36313-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h             |  2 +-
+ net/netfilter/ipvs/ip_vs_core.c | 67 +++++++++++++++++----------------
+ net/netfilter/ipvs/ip_vs_xmit.c |  2 +-
+ 3 files changed, 36 insertions(+), 35 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 6935ec09af24d..80110ec025002 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1707,7 +1707,7 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int dir, unsigned int toff,
+-                  bool has_ports);
++                  bool has_ports, struct ip_vs_iphdr *ciph);
+ #ifdef CONFIG_IP_VS_IPV6
+ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index e49a4840effb3..9c32d346e8400 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -747,28 +747,27 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
+  */
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int inout, unsigned int toff,
+-                  bool has_ports)
++                  bool has_ports, struct ip_vs_iphdr *ciph)
+ {
+       struct iphdr *iph        = ip_hdr(skb);
+       struct icmphdr *icmph    = (struct icmphdr *)(skb->data + toff);
+-      struct iphdr *ciph       = (struct iphdr *)(icmph + 1);
+-      unsigned int coff __maybe_unused = toff + sizeof(struct icmphdr);
++      struct iphdr *cih        = (struct iphdr *)(icmph + 1);
+       if (inout) {
+               iph->saddr = cp->vaddr.ip;
+               ip_send_check(iph);
+-              ciph->daddr = cp->vaddr.ip;
+-              ip_send_check(ciph);
++              cih->daddr = cp->vaddr.ip;
++              ip_send_check(cih);
+       } else {
+               iph->daddr = cp->daddr.ip;
+               ip_send_check(iph);
+-              ciph->saddr = cp->daddr.ip;
+-              ip_send_check(ciph);
++              cih->saddr = cp->daddr.ip;
++              ip_send_check(cih);
+       }
+       /* the TCP/UDP/SCTP port */
+       if (has_ports) {
+-              __be16 *ports = (void *)ciph + ciph->ihl*4;
++              __be16 *ports = (void *)(skb->data + ciph->len);
+               if (inout)
+                       ports[1] = cp->vport;
+@@ -782,10 +781,10 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       if (inout)
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered outgoing ICMP");
+       else
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered incoming ICMP");
+ }
+@@ -878,7 +877,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
+               ip_vs_nat_icmp_v6(skb, pp, cp, 1, toff, has_ports, ciph);
+       else
+ #endif
+-              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports);
++              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports, ciph);
+       if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
+               goto out;
+@@ -914,7 +913,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       struct ip_vs_iphdr ciph;
+       struct ip_vs_conn *cp;
+       struct ip_vs_protocol *pp;
+-      unsigned int offset, ihl;
++      unsigned int offset;
+       union nf_inet_addr snet;
+       *related = 1;
+@@ -927,7 +926,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+                       return NF_ACCEPT;
+       }
+-      ihl = ipvsh->len;
+       offset = ipvsh->len;
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
+@@ -953,11 +951,15 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      pp = ip_vs_proto_get(cih->protocol);
++      pp = ip_vs_proto_get(ciph.protocol);
+       if (!pp)
+               return NF_ACCEPT;
+@@ -968,8 +970,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking outgoing ICMP for");
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order */
+       cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
+                            ipvs, AF_INET, skb, &ciph);
+@@ -977,8 +977,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+               return NF_ACCEPT;
+       snet.ip = ipvsh->saddr.ip;
+-      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph, ihl,
+-                                  hooknum);
++      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph,
++                                  ipvsh->len, hooknum);
+ }
+ #ifdef CONFIG_IP_VS_IPV6
+@@ -1621,10 +1621,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!cih)
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      raddr = (union nf_inet_addr *)&cih->daddr;
+       hlen_ipip = cih->ihl * 4;
++      if (!(cih->version == 4 && hlen_ipip >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++      raddr = (union nf_inet_addr *)&cih->daddr;
+       /* Special case for errors for IPIP/UDP/GRE tunnel packets */
+       tunnel = false;
+@@ -1641,9 +1643,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+               if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP)
+                       return NF_ACCEPT;
+               offset += hlen_ipip;
+-              cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-              if (!(cih && cih->version == 4 && cih->ihl >= 5))
+-                      return NF_ACCEPT; /* The packet looks wrong, ignore */
+               tunnel = true;
+       } else if ((cih->protocol == IPPROTO_UDP ||     /* Can be UDP encap */
+                   cih->protocol == IPPROTO_GRE) &&    /* Can be GRE encap */
+@@ -1668,21 +1667,25 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+                       /* Skip IP and UDP/GRE tunnel headers */
+                       offset = offset2 + ulen;
+                       /* Now we should be at the original IP header */
+-                      cih = skb_header_pointer(skb, offset, sizeof(_ciph),
+-                                               &_ciph);
+-                      if (cih && cih->version == 4 && cih->ihl >= 5 &&
+-                          iproto == IPPROTO_IPIP)
++                      if (iproto == IPPROTO_IPIP)
+                               tunnel = true;
+                       else
+                               return NF_ACCEPT;
+               }
+       }
+-      pd = ip_vs_proto_data_get(ipvs, cih->protocol);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph))
++              return NF_ACCEPT;
++      pd = ip_vs_proto_data_get(ipvs, ciph.protocol);
+       if (!pd)
+               return NF_ACCEPT;
+       pp = pd->pp;
++      cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       /* Is the embedded protocol header present? */
+       if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
+               return NF_ACCEPT;
+@@ -1690,9 +1693,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking incoming ICMP for");
+-      offset2 = offset;
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order.
+        * For IPIP/UDP/GRE tunnel this is error for request, not for reply.
+        */
+@@ -1722,11 +1722,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       }
+       if (tunnel) {
+-              unsigned int hlen_orig = cih->ihl * 4;
++              unsigned int hlen_orig = ciph.len - ciph.off;
+               __be32 info = ic->un.gateway;
+               __u8 type = ic->type;
+               __u8 code = ic->code;
++              offset2 = offset;
+               /* Update the MTU */
+               if (ic->type == ICMP_DEST_UNREACH &&
+                   ic->code == ICMP_FRAG_NEEDED) {
+diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
+index c214e5d05524c..5b37e92df02c5 100644
+--- a/net/netfilter/ipvs/ip_vs_xmit.c
++++ b/net/netfilter/ipvs/ip_vs_xmit.c
+@@ -1551,7 +1551,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+       if (skb_cow(skb, rt->dst.dev->hard_header_len))
+               goto tx_error;
+-      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports);
++      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports, ciph);
+       /* Another hack: avoid icmp_send in ip_fragment */
+       skb->ignore_df = 1;
+-- 
+2.53.0
+
diff --git a/queue-6.6/ipvs-return-the-csum-validation-for-forward-hook.patch b/queue-6.6/ipvs-return-the-csum-validation-for-forward-hook.patch
new file mode 100644 (file)
index 0000000..594f1cd
--- /dev/null
@@ -0,0 +1,100 @@
+From 216d0c71944fb1b2bc5cc20ebeaec4c34a8208f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:06 +0300
+Subject: ipvs: return the csum validation for forward hook
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 99609cb0aa789c8d071050ce8579989551882cc6 ]
+
+Sashiko notes that playing games with the skb dst and rt
+flags instead of providing hooknum is not a good idea
+when validating the checksums.
+
+Also, skipping checksum validation for FORWARD packets
+risk silent data corruption, even if the only user is
+the FTP-CMD packets coming from the real server.
+
+Sashiko also noticed that by using common checksum
+helper in the previous commit we actually fixed old bug
+where the TCP/UDP checksum for IPv6 on CHECKSUM_COMPLETE
+was not validated correctly.
+
+Fixes: e876b75b9020 ("ipvs: fix the checksum validations")
+Link: https://sashiko.dev/#/patchset/20260722211420.153933-1-pablo%40netfilter.org
+Link: https://sashiko.dev/#/patchset/20260727185024.67534-1-ja%40ssi.bg
+Link: https://sashiko.dev/#/patchset/20260728202520.59179-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h                   | 19 +++++--------------
+ net/netfilter/ipvs/ip_vs_proto_sctp.c |  2 +-
+ 2 files changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 80110ec025002..1121845bcc2a6 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -24,9 +24,7 @@
+ #include <linux/netfilter.h>          /* for union nf_inet_addr */
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>                       /* for struct ipv6hdr */
+-#include <net/route.h>
+ #include <net/ipv6.h>
+-#include <net/ip6_fib.h>
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ #include <net/netfilter/nf_conntrack.h>
+ #endif
+@@ -1740,30 +1738,23 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+       return csum_partial(diff, sizeof(diff), oldsum);
+ }
+-static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
++static inline bool ip_vs_checksum_needed(struct sk_buff *skb)
+ {
+       /* Checksum unnecessary or already validated? */
+       if (skb_csum_unnecessary(skb))
+               return false;
+-      /* LOCAL_OUT ? */
+-      if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
++      /* Locally generated ? */
++      if (!skb->dev)
+               return false;
+-      /* !LOCAL_IN (FORWARD) ? */
+-      if (af == AF_INET6) {
+-              if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
+-                      return false;
+-      } else {
+-              if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+-                      return false;
+-      }
+       return true;
+ }
+ static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
+                                              int offset, int proto, int af)
+ {
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return true;
++      /* Validate csum even for FORWARD */
+       return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+index 3dbd3096e1637..c80567c73469b 100644
+--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+@@ -193,7 +193,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+       struct sctphdr *sh;
+       __le32 cmp, val;
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return 1;
+       sh = (struct sctphdr *)(skb->data + sctphoff);
+       cmp = sh->checksum;
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch b/queue-6.6/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
new file mode 100644 (file)
index 0000000..18efd91
--- /dev/null
@@ -0,0 +1,81 @@
+From 4962d904a54474e882985fd09f2fb9c7bc6cc78b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 13:15:08 +0000
+Subject: net/atm: fix slab-out-of-bounds read in vcc_setsockopt()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d0c80dbb970439bd2eeb0e5effff8c16a5f4e1e3 ]
+
+vcc_setsockopt() contained an ineffective optlen check:
+  if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+      return -EINVAL;
+
+If __SO_LEVEL_MATCH(optname, level) evaluated to false (e.g. if the caller
+passed a mismatched level), the length check optlen != __SO_SIZE(optname)
+was short-circuited and bypassed. Execution then fell through to switch(optname),
+calling copy_from_sockptr() assuming optval contained sufficient space.
+
+Furthermore, even if level matched, a cgroup BPF setsockopt filter could shrink
+optlen after entry. Because copy_from_sockptr() on kernel pointers uses memcpy(),
+this leads to a KASAN slab-out-of-bounds read when optlen is smaller than the
+expected structure size.
+
+Fix this by using copy_safe_from_sockptr(), which unconditionally validates
+that optlen is at least the expected size before copying. Also change the local
+'value' variable type from 'unsigned long' to 'int' so that SO_SETCLP matches
+its sizeof(int) ABI encoding on 64-bit systems.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+53ecc09fb81df10ef4de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=53ecc09fb81df10ef4de
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260805131508.3227331-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/atm/common.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/net/atm/common.c b/net/atm/common.c
+index 96f680a45e306..f3f68c231935a 100644
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+                  sockptr_t optval, unsigned int optlen)
+ {
+       struct atm_vcc *vcc;
+-      unsigned long value;
++      int value;
+       int error;
+       if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+@@ -772,8 +772,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+       {
+               struct atm_qos qos;
+-              if (copy_from_sockptr(&qos, optval, sizeof(qos)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&qos, sizeof(qos), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               error = check_qos(&qos);
+               if (error)
+                       return error;
+@@ -786,8 +788,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+               return 0;
+       }
+       case SO_SETCLP:
+-              if (copy_from_sockptr(&value, optval, sizeof(value)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&value, sizeof(value), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               if (value)
+                       vcc->atm_options |= ATM_ATMOPT_CLP;
+               else
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-6.6/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..48fc621
--- /dev/null
@@ -0,0 +1,42 @@
+From 923e2e30e6ae64462806cc2e9535e47ce567f000 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index 26d22bb04b879..e8cedc2608654 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1287,7 +1287,6 @@ static int hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-6.6/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..03191e9
--- /dev/null
@@ -0,0 +1,134 @@
+From 2e456ce684daae5f535abff9cdb7525703e1bfc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 0a33ab5f53fd3..dba0d73ac37d5 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1050,13 +1050,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1098,7 +1096,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1109,7 +1107,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       if (!tracer->str_db.loaded)
+@@ -1159,7 +1157,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mutex_lock(&tracer->state_lock);
+@@ -1188,7 +1186,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1240,7 +1238,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch b/queue-6.6/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
new file mode 100644 (file)
index 0000000..a8ee36d
--- /dev/null
@@ -0,0 +1,100 @@
+From 8ca54dc66807bcce17a66462f3b80e06e5e1eb47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 07:43:38 +0300
+Subject: net/mlx5e: TC, Check if flow is PEER before acquiring devcom lock
+
+From: Shay Drory <shayd@nvidia.com>
+
+[ Upstream commit 6ddfba2ea98db21b001e0e5c472499156224650c ]
+
+In case __mlx5e_add_fdb_flow() fails in lower levels, the flow is
+deleted via mlx5e_tc_del_flow(), and mlx5e_tc_del_flow() is acquiring
+ESW devcom lock without condition. In addition, in case of peer_flow,
+__mlx5e_add_fdb_flow() is called while holding ESW devcom comp lock.
+This results in an AA deadlock.
+
+To fix this, introduce a new PEER flag that is set on flows created as
+peer flows (the duplicate flows on peer devices), and check it in
+mlx5e_tc_del_flow() before acquiring ESW devcom lock.
+
+Lockdep splat:
+============================================
+WARNING: possible recursive locking detected
+============================================
+ Possible unsafe locking scenario:
+       CPU0
+       ----
+  lock(&comp->lock_key#2);
+  lock(&comp->lock_key#2);
+ *** DEADLOCK ***
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x69/0xa0
+ print_deadlock_bug.cold+0xbd/0xca
+ __lock_acquire+0x1671/0x2ec0
+ lock_acquire+0x10e/0x2e0
+ down_read+0x95/0x430
+ mlx5_devcom_for_each_peer_begin+0x4e/0xe0 [mlx5_core]
+ mlx5e_tc_del_flow+0x11d/0xa70 [mlx5_core]
+ mlx5e_flow_put+0x99/0x100 [mlx5_core]
+ __mlx5e_add_fdb_flow+0x409/0xf00 [mlx5_core]
+ mlx5e_configure_flower+0x2a86/0x4100 [mlx5_core]
+ mlx5e_rep_setup_tc_cls_flower+0x12f/0x1b0 [mlx5_core]
+ mlx5e_rep_setup_tc_cb+0x153/0x750 [mlx5_core]
+ tc_setup_cb_add+0x1dc/0x470
+ fl_change+0x2f4d/0x626d [cls_flower]
+ tc_new_tfilter+0x79b/0x2310
+ rtnetlink_rcv_msg+0x778/0xad0
+ do_syscall_64+0x70/0x960
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ </TASK>
+
+Fixes: 04de7dda7394 ("net/mlx5e: Infrastructure for duplicated offloading of TC flows")
+Signed-off-by: Shay Drory <shayd@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260728044338.2271143-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h | 1 +
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c      | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+index 6cc23af66b5be..a23d0df42f027 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+@@ -30,6 +30,7 @@ enum {
+       MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 9,
+       MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 10,
+       MLX5E_TC_FLOW_FLAG_USE_ACT_STATS         = MLX5E_TC_FLOW_BASE + 11,
++      MLX5E_TC_FLOW_FLAG_PEER                  = MLX5E_TC_FLOW_BASE + 12,
+ };
+ struct mlx5e_tc_flow_parse_attr {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index f1f4225057311..8c52bbeabb7e0 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -2043,7 +2043,8 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
+       if (mlx5e_is_eswitch_flow(flow)) {
+               struct mlx5_devcom_comp_dev *devcom = flow->priv->mdev->priv.eswitch->devcom;
+-              if (!mlx5_devcom_for_each_peer_begin(devcom)) {
++              if (flow_flag_test(flow, PEER) ||
++                  !mlx5_devcom_for_each_peer_begin(devcom)) {
+                       mlx5e_tc_del_fdb_flow(priv, flow);
+                       return;
+               }
+@@ -4489,6 +4490,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
+       else
+               in_mdev = priv->mdev;
++      flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_PEER);
+       parse_attr = flow->attr->parse_attr;
+       peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
+                                        parse_attr->filter_dev,
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-6.6/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..8294e86
--- /dev/null
@@ -0,0 +1,60 @@
+From 4bced815c3e2adf53e2ac833258c811ab8ffb06b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index 2f872d064396d..8cc538358f6a3 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-6.6/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..abb42b9
--- /dev/null
@@ -0,0 +1,78 @@
+From a045441708444ca097bbe8358aebfc6fd7996bbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index b80bd3a907739..52e261ce91e8e 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -893,8 +893,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -914,8 +912,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -930,6 +926,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-prestera-validate-firmware-header-length.patch b/queue-6.6/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..12dd342
--- /dev/null
@@ -0,0 +1,42 @@
+From 7e9094dca48e787324492070d823bddf0b571b43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index 35857dc19542f..5db2c9e5e077d 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -684,6 +684,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-6.6/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..b1ea26a
--- /dev/null
@@ -0,0 +1,45 @@
+From 522df6435251270ad6c72cd23231abc38e59640b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 87e6060c8bca7..846e95805c199 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -776,7 +776,6 @@ bool sk_mc_loop(struct sock *sk)
+               return inet6_sk(sk)->mc_loop;
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-cls_api-add-filter-counter.patch b/queue-6.6/net-sched-cls_api-add-filter-counter.patch
new file mode 100644 (file)
index 0000000..f67778b
--- /dev/null
@@ -0,0 +1,94 @@
+From f9b2cd440597e1f6e9864e5f0d66be4080ceefd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 20:47:35 +0000
+Subject: net: sched: cls_api: add filter counter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+
+[ Upstream commit 2081fd3445fec6b9813c20e8b910c2abd6de31cb ]
+
+Maintain a count of filters per block.
+
+Counter updates are protected by cb_lock, which is
+also used to protect the offload counters.
+
+Signed-off-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: a347304b2ca1 ("net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sch_generic.h |  2 ++
+ net/sched/cls_api.c       | 19 +++++++++++++++++++
+ 2 files changed, 21 insertions(+)
+
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index 5df841ed0aeaa..a94ff63e3cd5b 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -429,6 +429,7 @@ struct tcf_proto {
+        */
+       spinlock_t              lock;
+       bool                    deleting;
++      bool                    counted;
+       refcount_t              refcnt;
+       struct rcu_head         rcu;
+       struct hlist_node       destroy_ht_node;
+@@ -477,6 +478,7 @@ struct tcf_block {
+       struct flow_block flow_block;
+       struct list_head owner_list;
+       bool keep_dst;
++      atomic_t filtercnt; /* Number of filters */
+       atomic_t skipswcnt; /* Number of skip_sw filters */
+       atomic_t offloadcnt; /* Number of oddloaded filters */
+       unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 792e7040ebc1f..d25ac60259715 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -410,12 +410,30 @@ static void tcf_proto_get(struct tcf_proto *tp)
+       refcount_inc(&tp->refcnt);
+ }
++static void tcf_block_filter_cnt_update(struct tcf_block *block, bool *counted, bool add)
++{
++      lockdep_assert_not_held(&block->cb_lock);
++
++      down_write(&block->cb_lock);
++      if (*counted != add) {
++              if (add) {
++                      atomic_inc(&block->filtercnt);
++                      *counted = true;
++              } else {
++                      atomic_dec(&block->filtercnt);
++                      *counted = false;
++              }
++      }
++      up_write(&block->cb_lock);
++}
++
+ static void tcf_chain_put(struct tcf_chain *chain);
+ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
+                             bool sig_destroy, struct netlink_ext_ack *extack)
+ {
+       tp->ops->destroy(tp, rtnl_held, extack);
++      tcf_block_filter_cnt_update(tp->chain->block, &tp->counted, false);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
+       tcf_chain_put(tp->chain);
+@@ -2354,6 +2372,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
+       err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
+                             flags, extack);
+       if (err == 0) {
++              tcf_block_filter_cnt_update(block, &tp->counted, true);
+               tfilter_notify(net, skb, n, tp, block, q, parent, fh,
+                              RTM_NEWTFILTER, false, rtnl_held, extack);
+               tfilter_put(tp, fh);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-cls_api-add-skip_sw-counter.patch b/queue-6.6/net-sched-cls_api-add-skip_sw-counter.patch
new file mode 100644 (file)
index 0000000..e098d07
--- /dev/null
@@ -0,0 +1,66 @@
+From c9b21c1888961e4ed043378d29923e3d0cfe21e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 20:47:34 +0000
+Subject: net: sched: cls_api: add skip_sw counter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+
+[ Upstream commit f631ef39d81956a2ee69d25039781ceae1162f62 ]
+
+Maintain a count of skip_sw filters.
+
+This counter is protected by the cb_lock, and is updated
+at the same time as offloadcnt.
+
+Signed-off-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: a347304b2ca1 ("net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sch_generic.h | 1 +
+ net/sched/cls_api.c       | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index 385af747b0b4e..5df841ed0aeaa 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -477,6 +477,7 @@ struct tcf_block {
+       struct flow_block flow_block;
+       struct list_head owner_list;
+       bool keep_dst;
++      atomic_t skipswcnt; /* Number of skip_sw filters */
+       atomic_t offloadcnt; /* Number of oddloaded filters */
+       unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */
+       unsigned int lockeddevcnt; /* Number of devs that require rtnl lock. */
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index e259ec6ed145d..792e7040ebc1f 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -3478,6 +3478,8 @@ static void tcf_block_offload_inc(struct tcf_block *block, u32 *flags)
+       if (*flags & TCA_CLS_FLAGS_IN_HW)
+               return;
+       *flags |= TCA_CLS_FLAGS_IN_HW;
++      if (tc_skip_sw(*flags))
++              atomic_inc(&block->skipswcnt);
+       atomic_inc(&block->offloadcnt);
+ }
+@@ -3486,6 +3488,8 @@ static void tcf_block_offload_dec(struct tcf_block *block, u32 *flags)
+       if (!(*flags & TCA_CLS_FLAGS_IN_HW))
+               return;
+       *flags &= ~TCA_CLS_FLAGS_IN_HW;
++      if (tc_skip_sw(*flags))
++              atomic_dec(&block->skipswcnt);
+       atomic_dec(&block->offloadcnt);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch b/queue-6.6/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
new file mode 100644 (file)
index 0000000..bcdf6ea
--- /dev/null
@@ -0,0 +1,116 @@
+From a5018ba5e92d2c8478278db4210c7cf49590761e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 08:56:32 -0400
+Subject: net/sched: cls_api: Always acquire rtnl_lock when destroying locked
+ classifiers
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit a347304b2ca1a5377d5bd2d8a72e4b4f12afe648 ]
+
+Another challenge with unlocked filters.
+There is a short window in tc_new_tfilter where a tcf_proto can be found
+and briefly referenced by a totally unrelated, unlocked classifier's request
+and cause a race.
+
+Feng created a poc which created this race with two threads, one creating a
+u32 filter and other a flower filter in the same chain/prio:
+
+1. Both threads enter tc_new_tfilter, both find the chain empty, both
+   drop filter_chain_lock
+2. u32 finishes tcf_proto_create("u32") first, calls
+   tcf_chain_tp_insert_unique() -> inserts u32_tp into the chain
+3. flower finishes tcf_proto_create("flower") later, calls
+   tcf_chain_tp_insert_unique() -> tcf_chain_tp_find() now sees u32_tp
+   already there, takes a reference on it, destroys flower's own tp_new
+   and returns u32_tp to the caller.
+
+Flower then hits the kind mismatch check (because it requested for kind
+"flower" but tp->ops->kind is "u32") and goes through the errout path
+which calls tcf_proto_put() on u32_tp. If the u32 thread has already
+gone through its own errout (its change() call failed on the PoC's empty
+options) and dropped its create and insert refs, flower's put is the
+last one and drops u32_tp's refcnt to zero.
+
+At this point tp->ops->destroy() runs in a context that never took
+rtnl_lock. When that happens, it might cause a UAF like the following
+(illustrated by the PoC):
+
+[  +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
+[  +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524
+
+  Call Trace:
+   u32_init (net/sched/cls_u32.c:393)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Allocated by task 526:
+   u32_init (net/sched/cls_u32.c:378)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Freed by task 522:
+   kfree
+   u32_destroy (net/sched/cls_u32.c:662)
+   tcf_proto_destroy (net/sched/cls_api.c:446)
+   tcf_proto_put (net/sched/cls_api.c:459)
+   tc_new_tfilter (net/sched/cls_api.c:2459)
+
+Fix this by having tcf_proto_destroy() take rtnl_lock around
+tp->ops->destroy() for locked classifiers whenever rtnl is not held.
+
+To explain why I used a temp variable "not_lockless" I'd like to point to a
+semi-related note on rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (adding here
+for future cleanup if deemed necessary):
+The rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are
+redundant sources of truth for whether rtnl_lock is held. Among the nine
+classifier destroy(..rtnl_held..) callbacks, only flower consults the
+rtnl_held parameter which it propagates to tc_setup_cb_destroy()
+and tc_setup_cb_call(). The other eight (u32, flow, bpf, cgroup, route, basic,
+fw, mall) ignore it entirely;-> those that call tc_setup_cb_destroy()
+(u32, bpf, mall) hardcode true always instead of forwarding the parameter.
+
+A future cleanup should remove the rtnl_held parameter from the destroy callback
+signature entirely and have callers rely solely on their knowledge whether
+they are running in an unlocked context.
+
+Fixes: 12db03b65c2b ("net: sched: extend proto ops to support unlocked classifiers")
+Reported-by: Feng Xue <feng.xue@outlook.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260801125632.360365-1-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_api.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index f107afdd36bbd..ff6af03cb855d 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -443,7 +443,22 @@ static void tcf_chain_put(struct tcf_chain *chain);
+ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
+                             bool sig_destroy, struct netlink_ext_ack *extack)
+ {
+-      tp->ops->destroy(tp, rtnl_held, extack);
++      /* A locked classifier's destroy callback (e.g. u32_destroy) uses
++       * rtnl_dereference() and mutates shared structures (e.g. the
++       * tc_u_common hash list) that are only safe under rtnl_lock. When an
++       * unlocked classifier's request (e.g. flower on ingress) loses the
++       * tcf_chain_tp_insert_unique() race and ends up dropping the last
++       * reference on a locked classifier's proto, destroy() would run
++       * without rtnl held. Take it here in that case.
++       */
++      bool not_lockless = !rtnl_held &&
++              !(tp->ops->flags & TCF_PROTO_OPS_DOIT_UNLOCKED);
++
++      if (not_lockless)
++              rtnl_lock();
++      tp->ops->destroy(tp, rtnl_held || not_lockless, extack);
++      if (not_lockless)
++              rtnl_unlock();
+       tcf_proto_count_usesw(tp, false);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-cls_api-fix-slab-use-after-free-in-fl_dump.patch b/queue-6.6/net-sched-cls_api-fix-slab-use-after-free-in-fl_dump.patch
new file mode 100644 (file)
index 0000000..9721f6d
--- /dev/null
@@ -0,0 +1,198 @@
+From e76ee5f3b2c5e990e3d22ff09f1db08e2f766e9c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 16:48:17 +0300
+Subject: net: sched: cls_api: fix slab-use-after-free in fl_dump_key
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit 2ecd487b670fcbb1ad4893fff1af4aafdecb6023 ]
+
+The filter counter is updated under the protection of cb_lock in the
+cited commit. While waiting for the lock, it's possible the filter is
+being deleted by other thread, and thus causes UAF when dump it.
+
+Fix this issue by moving tcf_block_filter_cnt_update() after
+tfilter_put().
+
+ ==================================================================
+ BUG: KASAN: slab-use-after-free in fl_dump_key+0x1d3e/0x20d0 [cls_flower]
+ Read of size 4 at addr ffff88814f864000 by task tc/2973
+
+ CPU: 7 PID: 2973 Comm: tc Not tainted 6.9.0-rc2_for_upstream_debug_2024_04_02_12_41 #1
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+ Call Trace:
+  <TASK>
+  dump_stack_lvl+0x7e/0xc0
+  print_report+0xc1/0x600
+  ? __virt_addr_valid+0x1cf/0x390
+  ? fl_dump_key+0x1d3e/0x20d0 [cls_flower]
+  ? fl_dump_key+0x1d3e/0x20d0 [cls_flower]
+  kasan_report+0xb9/0xf0
+  ? fl_dump_key+0x1d3e/0x20d0 [cls_flower]
+  fl_dump_key+0x1d3e/0x20d0 [cls_flower]
+  ? lock_acquire+0x1c2/0x530
+  ? fl_dump+0x172/0x5c0 [cls_flower]
+  ? lockdep_hardirqs_on_prepare+0x400/0x400
+  ? fl_dump_key_options.part.0+0x10f0/0x10f0 [cls_flower]
+  ? do_raw_spin_lock+0x12d/0x270
+  ? spin_bug+0x1d0/0x1d0
+  fl_dump+0x21d/0x5c0 [cls_flower]
+  ? fl_tmplt_dump+0x1f0/0x1f0 [cls_flower]
+  ? nla_put+0x15f/0x1c0
+  tcf_fill_node+0x51b/0x9a0
+  ? tc_skb_ext_tc_enable+0x150/0x150
+  ? __alloc_skb+0x17b/0x310
+  ? __build_skb_around+0x340/0x340
+  ? down_write+0x1b0/0x1e0
+  tfilter_notify+0x1a5/0x390
+  ? fl_terse_dump+0x400/0x400 [cls_flower]
+  tc_new_tfilter+0x963/0x2170
+  ? tc_del_tfilter+0x1490/0x1490
+  ? print_usage_bug.part.0+0x670/0x670
+  ? lock_downgrade+0x680/0x680
+  ? security_capable+0x51/0x90
+  ? tc_del_tfilter+0x1490/0x1490
+  rtnetlink_rcv_msg+0x75e/0xac0
+  ? if_nlmsg_stats_size+0x4c0/0x4c0
+  ? lockdep_set_lock_cmp_fn+0x190/0x190
+  ? __netlink_lookup+0x35e/0x6e0
+  netlink_rcv_skb+0x12c/0x360
+  ? if_nlmsg_stats_size+0x4c0/0x4c0
+  ? netlink_ack+0x15e0/0x15e0
+  ? lockdep_hardirqs_on_prepare+0x400/0x400
+  ? netlink_deliver_tap+0xcd/0xa60
+  ? netlink_deliver_tap+0xcd/0xa60
+  ? netlink_deliver_tap+0x1c9/0xa60
+  netlink_unicast+0x43e/0x700
+  ? netlink_attachskb+0x750/0x750
+  ? lock_acquire+0x1c2/0x530
+  ? __might_fault+0xbb/0x170
+  netlink_sendmsg+0x749/0xc10
+  ? netlink_unicast+0x700/0x700
+  ? __might_fault+0xbb/0x170
+  ? netlink_unicast+0x700/0x700
+  __sock_sendmsg+0xc5/0x190
+  ____sys_sendmsg+0x534/0x6b0
+  ? import_iovec+0x7/0x10
+  ? kernel_sendmsg+0x30/0x30
+  ? __copy_msghdr+0x3c0/0x3c0
+  ? entry_SYSCALL_64_after_hwframe+0x46/0x4e
+  ? lock_acquire+0x1c2/0x530
+  ? __virt_addr_valid+0x116/0x390
+  ___sys_sendmsg+0xeb/0x170
+  ? __virt_addr_valid+0x1ca/0x390
+  ? copy_msghdr_from_user+0x110/0x110
+  ? __delete_object+0xb8/0x100
+  ? __virt_addr_valid+0x1cf/0x390
+  ? do_sys_openat2+0x102/0x150
+  ? lockdep_hardirqs_on_prepare+0x284/0x400
+  ? do_sys_openat2+0x102/0x150
+  ? __fget_light+0x53/0x1d0
+  ? sockfd_lookup_light+0x1a/0x150
+  __sys_sendmsg+0xb5/0x140
+  ? __sys_sendmsg_sock+0x20/0x20
+  ? lock_downgrade+0x680/0x680
+  do_syscall_64+0x70/0x140
+  entry_SYSCALL_64_after_hwframe+0x46/0x4e
+ RIP: 0033:0x7f98e3713367
+ Code: 0e 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b9 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 89 74 24 10
+ RSP: 002b:00007ffc74a64608 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+ RAX: ffffffffffffffda RBX: 000000000047eae0 RCX: 00007f98e3713367
+ RDX: 0000000000000000 RSI: 00007ffc74a64670 RDI: 0000000000000003
+ RBP: 0000000000000008 R08: 0000000000000000 R09: 0000000000000000
+ R10: 00007f98e360c5e8 R11: 0000000000000246 R12: 00007ffc74a6a508
+ R13: 00000000660d518d R14: 0000000000484a80 R15: 00007ffc74a6a50b
+  </TASK>
+
+ Allocated by task 2973:
+  kasan_save_stack+0x20/0x40
+  kasan_save_track+0x10/0x30
+  __kasan_kmalloc+0x77/0x90
+  fl_change+0x27a6/0x4540 [cls_flower]
+  tc_new_tfilter+0x879/0x2170
+  rtnetlink_rcv_msg+0x75e/0xac0
+  netlink_rcv_skb+0x12c/0x360
+  netlink_unicast+0x43e/0x700
+  netlink_sendmsg+0x749/0xc10
+  __sock_sendmsg+0xc5/0x190
+  ____sys_sendmsg+0x534/0x6b0
+  ___sys_sendmsg+0xeb/0x170
+  __sys_sendmsg+0xb5/0x140
+  do_syscall_64+0x70/0x140
+  entry_SYSCALL_64_after_hwframe+0x46/0x4e
+
+ Freed by task 283:
+  kasan_save_stack+0x20/0x40
+  kasan_save_track+0x10/0x30
+  kasan_save_free_info+0x37/0x50
+  poison_slab_object+0x105/0x190
+  __kasan_slab_free+0x11/0x30
+  kfree+0x111/0x340
+  process_one_work+0x787/0x1490
+  worker_thread+0x586/0xd30
+  kthread+0x2df/0x3b0
+  ret_from_fork+0x2d/0x70
+  ret_from_fork_asm+0x11/0x20
+
+ Last potentially related work creation:
+  kasan_save_stack+0x20/0x40
+  __kasan_record_aux_stack+0x9b/0xb0
+  insert_work+0x25/0x1b0
+  __queue_work+0x640/0xc90
+  rcu_work_rcufn+0x42/0x70
+  rcu_core+0x6a9/0x1850
+  __do_softirq+0x264/0x88f
+
+ Second to last potentially related work creation:
+  kasan_save_stack+0x20/0x40
+  __kasan_record_aux_stack+0x9b/0xb0
+  __call_rcu_common.constprop.0+0x6f/0xac0
+  queue_rcu_work+0x56/0x70
+  fl_mask_put+0x20d/0x270 [cls_flower]
+  __fl_delete+0x352/0x6b0 [cls_flower]
+  fl_delete+0x97/0x160 [cls_flower]
+  tc_del_tfilter+0x7d1/0x1490
+  rtnetlink_rcv_msg+0x75e/0xac0
+  netlink_rcv_skb+0x12c/0x360
+  netlink_unicast+0x43e/0x700
+  netlink_sendmsg+0x749/0xc10
+  __sock_sendmsg+0xc5/0x190
+  ____sys_sendmsg+0x534/0x6b0
+  ___sys_sendmsg+0xeb/0x170
+  __sys_sendmsg+0xb5/0x140
+  do_syscall_64+0x70/0x140
+  entry_SYSCALL_64_after_hwframe+0x46/0x4e
+
+Fixes: 2081fd3445fe ("net: sched: cls_api: add filter counter")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Tested-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: a347304b2ca1 ("net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_api.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index f16cfc23014b2..1eedeaf427298 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -2390,10 +2390,10 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
+       err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
+                             flags, extack);
+       if (err == 0) {
+-              tcf_block_filter_cnt_update(block, &tp->counted, true);
+               tfilter_notify(net, skb, n, tp, block, q, parent, fh,
+                              RTM_NEWTFILTER, false, rtnl_held, extack);
+               tfilter_put(tp, fh);
++              tcf_block_filter_cnt_update(block, &tp->counted, true);
+               /* q pointer is NULL for shared blocks */
+               if (q)
+                       q->flags &= ~TCQ_F_CAN_BYPASS;
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-6.6/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..e6ad7dd
--- /dev/null
@@ -0,0 +1,142 @@
+From 4c756026630c2e20dc03f88374d22f3b76e18a49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index 1e20bbd687f1d..fd72ab9d19eac 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -52,6 +52,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -66,9 +67,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -81,9 +84,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -297,6 +302,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -307,6 +319,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -334,11 +351,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -553,7 +570,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-make-skip_sw-actually-skip-software.patch b/queue-6.6/net-sched-make-skip_sw-actually-skip-software.patch
new file mode 100644 (file)
index 0000000..b29523c
--- /dev/null
@@ -0,0 +1,208 @@
+From 72ece3300ede9fdedf0ab45835e4bd8e06b43e0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 20:47:36 +0000
+Subject: net: sched: make skip_sw actually skip software
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+
+[ Upstream commit 047f340b36fc550c0fc6a8947fc0a1f8e429e9ab ]
+
+TC filters come in 3 variants:
+- no flag (try to process in hardware, but fallback to software))
+- skip_hw (do not process filter by hardware)
+- skip_sw (do not process filter by software)
+
+However skip_sw is implemented so that the skip_sw
+flag can first be checked, after it has been matched.
+
+IMHO it's common when using skip_sw, to use it on all rules.
+
+So if all filters in a block is skip_sw filters, then
+we can bail early, we can thus avoid having to match
+the filters, just to check for the skip_sw flag.
+
+This patch adds a bypass, for when only TC skip_sw rules
+are used. The bypass is guarded by a static key, to avoid
+harming other workloads.
+
+There are 3 ways that a packet from a skip_sw ruleset, can
+end up in the kernel path. Although the send packets to a
+non-existent chain way is only improved a few percents, then
+I believe it's worth optimizing the trap and fall-though
+use-cases.
+
+ +----------------------------+--------+--------+--------+
+ | Test description           | Pre-   | Post-  | Rel.   |
+ |                            | kpps   | kpps   | chg.   |
+ +----------------------------+--------+--------+--------+
+ | basic forwarding + notrack | 3589.3 | 3587.9 |  1.00x |
+ | switch to eswitch mode     | 3081.8 | 3094.7 |  1.00x |
+ | add ingress qdisc          | 3042.9 | 3063.6 |  1.01x |
+ | tc forward in hw / skip_sw |37024.7 |37028.4 |  1.00x |
+ | tc forward in sw / skip_hw | 3245.0 | 3245.3 |  1.00x |
+ +----------------------------+--------+--------+--------+
+ | tests with only skip_sw rules below:                  |
+ +----------------------------+--------+--------+--------+
+ | 1 non-matching rule        | 2694.7 | 3058.7 |  1.14x |
+ | 1 n-m rule, match trap     | 2611.2 | 3323.1 |  1.27x |
+ | 1 n-m rule, goto non-chain | 2886.8 | 2945.9 |  1.02x |
+ | 5 non-matching rules       | 1958.2 | 3061.3 |  1.56x |
+ | 5 n-m rules, match trap    | 1911.9 | 3327.0 |  1.74x |
+ | 5 n-m rules, goto non-chain| 2883.1 | 2947.5 |  1.02x |
+ | 10 non-matching rules      | 1466.3 | 3062.8 |  2.09x |
+ | 10 n-m rules, match trap   | 1444.3 | 3317.9 |  2.30x |
+ | 10 n-m rules,goto non-chain| 2883.1 | 2939.5 |  1.02x |
+ | 25 non-matching rules      |  838.5 | 3058.9 |  3.65x |
+ | 25 n-m rules, match trap   |  824.5 | 3323.0 |  4.03x |
+ | 25 n-m rules,goto non-chain| 2875.8 | 2944.7 |  1.02x |
+ | 50 non-matching rules      |  488.1 | 3054.7 |  6.26x |
+ | 50 n-m rules, match trap   |  484.9 | 3318.5 |  6.84x |
+ | 50 n-m rules,goto non-chain| 2884.1 | 2939.7 |  1.02x |
+ +----------------------------+--------+--------+--------+
+
+perf top (25 n-m skip_sw rules - pre patch):
+  20.39%  [kernel]  [k] __skb_flow_dissect
+  16.43%  [kernel]  [k] rhashtable_jhash2
+  10.58%  [kernel]  [k] fl_classify
+  10.23%  [kernel]  [k] fl_mask_lookup
+   4.79%  [kernel]  [k] memset_orig
+   2.58%  [kernel]  [k] tcf_classify
+   1.47%  [kernel]  [k] __x86_indirect_thunk_rax
+   1.42%  [kernel]  [k] __dev_queue_xmit
+   1.36%  [kernel]  [k] nft_do_chain
+   1.21%  [kernel]  [k] __rcu_read_lock
+
+perf top (25 n-m skip_sw rules - post patch):
+   5.12%  [kernel]  [k] __dev_queue_xmit
+   4.77%  [kernel]  [k] nft_do_chain
+   3.65%  [kernel]  [k] dev_gro_receive
+   3.41%  [kernel]  [k] check_preemption_disabled
+   3.14%  [kernel]  [k] mlx5e_skb_from_cqe_mpwrq_nonlinear
+   2.88%  [kernel]  [k] __netif_receive_skb_core.constprop.0
+   2.49%  [kernel]  [k] mlx5e_xmit
+   2.15%  [kernel]  [k] ip_forward
+   1.95%  [kernel]  [k] mlx5e_tc_restore_tunnel
+   1.92%  [kernel]  [k] vlan_gro_receive
+
+Test setup:
+ DUT: Intel Xeon D-1518 (2.20GHz) w/ Nvidia/Mellanox ConnectX-6 Dx 2x100G
+ Data rate measured on switch (Extreme X690), and DUT connected as
+ a router on a stick, with pktgen and pktsink as VLANs.
+ Pktgen-dpdk was in range 36.6-37.7 Mpps 64B packets across all tests.
+ Full test data at https://files.fiberby.net/ast/2024/tc_skip_sw/v2_tests/
+
+Signed-off-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: a347304b2ca1 ("net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/pkt_cls.h     |  9 +++++++++
+ include/net/sch_generic.h |  1 +
+ net/core/dev.c            | 10 ++++++++++
+ net/sched/cls_api.c       | 18 ++++++++++++++++++
+ 4 files changed, 38 insertions(+)
+
+diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
+index ccc1c698ed007..0c1a1e366e8eb 100644
+--- a/include/net/pkt_cls.h
++++ b/include/net/pkt_cls.h
+@@ -72,6 +72,15 @@ static inline bool tcf_block_non_null_shared(struct tcf_block *block)
+       return block && block->index;
+ }
++#ifdef CONFIG_NET_CLS_ACT
++DECLARE_STATIC_KEY_FALSE(tcf_bypass_check_needed_key);
++
++static inline bool tcf_block_bypass_sw(struct tcf_block *block)
++{
++      return block && block->bypass_wanted;
++}
++#endif
++
+ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
+ {
+       WARN_ON(tcf_block_shared(block));
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index a94ff63e3cd5b..18ba0226b624f 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -478,6 +478,7 @@ struct tcf_block {
+       struct flow_block flow_block;
+       struct list_head owner_list;
+       bool keep_dst;
++      bool bypass_wanted;
+       atomic_t filtercnt; /* Number of filters */
+       atomic_t skipswcnt; /* Number of skip_sw filters */
+       atomic_t offloadcnt; /* Number of oddloaded filters */
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 0cc03e6c6fb14..31469d53e067d 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2146,6 +2146,11 @@ void net_dec_egress_queue(void)
+ EXPORT_SYMBOL_GPL(net_dec_egress_queue);
+ #endif
++#ifdef CONFIG_NET_CLS_ACT
++DEFINE_STATIC_KEY_FALSE(tcf_bypass_check_needed_key);
++EXPORT_SYMBOL(tcf_bypass_check_needed_key);
++#endif
++
+ DEFINE_STATIC_KEY_FALSE(netstamp_needed_key);
+ EXPORT_SYMBOL(netstamp_needed_key);
+ #ifdef CONFIG_JUMP_LABEL
+@@ -4030,6 +4035,11 @@ static int tc_run(struct tcx_entry *entry, struct sk_buff *skb)
+       if (!miniq)
+               return ret;
++      if (static_branch_unlikely(&tcf_bypass_check_needed_key)) {
++              if (tcf_block_bypass_sw(miniq->block))
++                      return ret;
++      }
++
+       tc_skb_cb(skb)->mru = 0;
+       tc_skb_cb(skb)->post_ct = false;
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index d25ac60259715..f16cfc23014b2 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -410,6 +410,23 @@ static void tcf_proto_get(struct tcf_proto *tp)
+       refcount_inc(&tp->refcnt);
+ }
++static void tcf_maintain_bypass(struct tcf_block *block)
++{
++      int filtercnt = atomic_read(&block->filtercnt);
++      int skipswcnt = atomic_read(&block->skipswcnt);
++      bool bypass_wanted = filtercnt > 0 && filtercnt == skipswcnt;
++
++      if (bypass_wanted != block->bypass_wanted) {
++#ifdef CONFIG_NET_CLS_ACT
++              if (bypass_wanted)
++                      static_branch_inc(&tcf_bypass_check_needed_key);
++              else
++                      static_branch_dec(&tcf_bypass_check_needed_key);
++#endif
++              block->bypass_wanted = bypass_wanted;
++      }
++}
++
+ static void tcf_block_filter_cnt_update(struct tcf_block *block, bool *counted, bool add)
+ {
+       lockdep_assert_not_held(&block->cb_lock);
+@@ -424,6 +441,7 @@ static void tcf_block_filter_cnt_update(struct tcf_block *block, bool *counted,
+                       *counted = false;
+               }
+       }
++      tcf_maintain_bypass(block);
+       up_write(&block->cb_lock);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-refine-software-bypass-handling-in-tc_run.patch b/queue-6.6/net-sched-refine-software-bypass-handling-in-tc_run.patch
new file mode 100644 (file)
index 0000000..e90f321
--- /dev/null
@@ -0,0 +1,363 @@
+From d39609f033baec27a962861e40a96c44903d464c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 09:27:54 -0500
+Subject: net: sched: refine software bypass handling in tc_run
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit a12c76a03386e32413ae8eaaefa337e491880632 ]
+
+This patch addresses issues with filter counting in block (tcf_block),
+particularly for software bypass scenarios, by introducing a more
+accurate mechanism using useswcnt.
+
+Previously, filtercnt and skipswcnt were introduced by:
+
+  Commit 2081fd3445fe ("net: sched: cls_api: add filter counter") and
+  Commit f631ef39d819 ("net: sched: cls_api: add skip_sw counter")
+
+  filtercnt tracked all tp (tcf_proto) objects added to a block, and
+  skipswcnt counted tp objects with the skipsw attribute set.
+
+The problem is: a single tp can contain multiple filters, some with skipsw
+and others without. The current implementation fails in the case:
+
+  When the first filter in a tp has skipsw, both skipswcnt and filtercnt
+  are incremented, then adding a second filter without skipsw to the same
+  tp does not modify these counters because tp->counted is already set.
+
+  This results in bypass software behavior based solely on skipswcnt
+  equaling filtercnt, even when the block includes filters without
+  skipsw. Consequently, filters without skipsw are inadvertently bypassed.
+
+To address this, the patch introduces useswcnt in block to explicitly count
+tp objects containing at least one filter without skipsw. Key changes
+include:
+
+  Whenever a filter without skipsw is added, its tp is marked with usesw
+  and counted in useswcnt. tc_run() now uses useswcnt to determine software
+  bypass, eliminating reliance on filtercnt and skipswcnt.
+
+  This refined approach prevents software bypass for blocks containing
+  mixed filters, ensuring correct behavior in tc_run().
+
+Additionally, as atomic operations on useswcnt ensure thread safety and
+tp->lock guards access to tp->usesw and tp->counted, the broader lock
+down_write(&block->cb_lock) is no longer required in tc_new_tfilter(),
+and this resolves a performance regression caused by the filter counting
+mechanism during parallel filter insertions.
+
+  The improvement can be demonstrated using the following script:
+
+  # cat insert_tc_rules.sh
+
+    tc qdisc add dev ens1f0np0 ingress
+    for i in $(seq 16); do
+        taskset -c $i tc -b rules_$i.txt &
+    done
+    wait
+
+  Each of rules_$i.txt files above includes 100000 tc filter rules to a
+  mlx5 driver NIC ens1f0np0.
+
+  Without this patch:
+
+  # time sh insert_tc_rules.sh
+
+    real    0m50.780s
+    user    0m23.556s
+    sys            4m13.032s
+
+  With this patch:
+
+  # time sh insert_tc_rules.sh
+
+    real    0m17.718s
+    user    0m7.807s
+    sys     3m45.050s
+
+Fixes: 047f340b36fc ("net: sched: make skip_sw actually skip software")
+Reported-by: Shuang Li <shuali@redhat.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Reviewed-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+Tested-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: a347304b2ca1 ("net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/pkt_cls.h     | 13 +++++++--
+ include/net/sch_generic.h |  5 ++--
+ net/core/dev.c            | 15 ++++++-----
+ net/sched/cls_api.c       | 57 ++++++++++++++++-----------------------
+ net/sched/cls_bpf.c       |  2 ++
+ net/sched/cls_flower.c    |  2 ++
+ net/sched/cls_matchall.c  |  2 ++
+ net/sched/cls_u32.c       |  4 +++
+ 8 files changed, 55 insertions(+), 45 deletions(-)
+
+diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
+index 0c1a1e366e8eb..307478c233223 100644
+--- a/include/net/pkt_cls.h
++++ b/include/net/pkt_cls.h
+@@ -73,11 +73,11 @@ static inline bool tcf_block_non_null_shared(struct tcf_block *block)
+ }
+ #ifdef CONFIG_NET_CLS_ACT
+-DECLARE_STATIC_KEY_FALSE(tcf_bypass_check_needed_key);
++DECLARE_STATIC_KEY_FALSE(tcf_sw_enabled_key);
+ static inline bool tcf_block_bypass_sw(struct tcf_block *block)
+ {
+-      return block && block->bypass_wanted;
++      return block && !atomic_read(&block->useswcnt);
+ }
+ #endif
+@@ -759,6 +759,15 @@ tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common,
+               cls_common->extack = extack;
+ }
++static inline void tcf_proto_update_usesw(struct tcf_proto *tp, u32 flags)
++{
++      if (tp->usesw)
++              return;
++      if (tc_skip_sw(flags) && tc_in_hw(flags))
++              return;
++      tp->usesw = true;
++}
++
+ #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
+ static inline struct tc_skb_ext *tc_skb_ext_alloc(struct sk_buff *skb)
+ {
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index 18ba0226b624f..6ec258d0278e3 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -430,6 +430,7 @@ struct tcf_proto {
+       spinlock_t              lock;
+       bool                    deleting;
+       bool                    counted;
++      bool                    usesw;
+       refcount_t              refcnt;
+       struct rcu_head         rcu;
+       struct hlist_node       destroy_ht_node;
+@@ -478,9 +479,7 @@ struct tcf_block {
+       struct flow_block flow_block;
+       struct list_head owner_list;
+       bool keep_dst;
+-      bool bypass_wanted;
+-      atomic_t filtercnt; /* Number of filters */
+-      atomic_t skipswcnt; /* Number of skip_sw filters */
++      atomic_t useswcnt;
+       atomic_t offloadcnt; /* Number of oddloaded filters */
+       unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */
+       unsigned int lockeddevcnt; /* Number of devs that require rtnl lock. */
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 31469d53e067d..0fa5431de2cc0 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2147,8 +2147,8 @@ EXPORT_SYMBOL_GPL(net_dec_egress_queue);
+ #endif
+ #ifdef CONFIG_NET_CLS_ACT
+-DEFINE_STATIC_KEY_FALSE(tcf_bypass_check_needed_key);
+-EXPORT_SYMBOL(tcf_bypass_check_needed_key);
++DEFINE_STATIC_KEY_FALSE(tcf_sw_enabled_key);
++EXPORT_SYMBOL(tcf_sw_enabled_key);
+ #endif
+ DEFINE_STATIC_KEY_FALSE(netstamp_needed_key);
+@@ -4035,10 +4035,13 @@ static int tc_run(struct tcx_entry *entry, struct sk_buff *skb)
+       if (!miniq)
+               return ret;
+-      if (static_branch_unlikely(&tcf_bypass_check_needed_key)) {
+-              if (tcf_block_bypass_sw(miniq->block))
+-                      return ret;
+-      }
++      /* Global bypass */
++      if (!static_branch_likely(&tcf_sw_enabled_key))
++              return ret;
++
++      /* Block-wise bypass */
++      if (tcf_block_bypass_sw(miniq->block))
++              return ret;
+       tc_skb_cb(skb)->mru = 0;
+       tc_skb_cb(skb)->post_ct = false;
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 1eedeaf427298..f107afdd36bbd 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -390,6 +390,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
+       tp->protocol = protocol;
+       tp->prio = prio;
+       tp->chain = chain;
++      tp->usesw = !tp->ops->reoffload;
+       spin_lock_init(&tp->lock);
+       refcount_set(&tp->refcnt, 1);
+@@ -410,39 +411,31 @@ static void tcf_proto_get(struct tcf_proto *tp)
+       refcount_inc(&tp->refcnt);
+ }
+-static void tcf_maintain_bypass(struct tcf_block *block)
++static void tcf_proto_count_usesw(struct tcf_proto *tp, bool add)
+ {
+-      int filtercnt = atomic_read(&block->filtercnt);
+-      int skipswcnt = atomic_read(&block->skipswcnt);
+-      bool bypass_wanted = filtercnt > 0 && filtercnt == skipswcnt;
+-
+-      if (bypass_wanted != block->bypass_wanted) {
+ #ifdef CONFIG_NET_CLS_ACT
+-              if (bypass_wanted)
+-                      static_branch_inc(&tcf_bypass_check_needed_key);
+-              else
+-                      static_branch_dec(&tcf_bypass_check_needed_key);
+-#endif
+-              block->bypass_wanted = bypass_wanted;
++      struct tcf_block *block = tp->chain->block;
++      bool counted = false;
++
++      if (!add) {
++              if (tp->usesw && tp->counted) {
++                      if (!atomic_dec_return(&block->useswcnt))
++                              static_branch_dec(&tcf_sw_enabled_key);
++                      tp->counted = false;
++              }
++              return;
+       }
+-}
+-
+-static void tcf_block_filter_cnt_update(struct tcf_block *block, bool *counted, bool add)
+-{
+-      lockdep_assert_not_held(&block->cb_lock);
+-      down_write(&block->cb_lock);
+-      if (*counted != add) {
+-              if (add) {
+-                      atomic_inc(&block->filtercnt);
+-                      *counted = true;
+-              } else {
+-                      atomic_dec(&block->filtercnt);
+-                      *counted = false;
+-              }
++      spin_lock(&tp->lock);
++      if (tp->usesw && !tp->counted) {
++              counted = true;
++              tp->counted = true;
+       }
+-      tcf_maintain_bypass(block);
+-      up_write(&block->cb_lock);
++      spin_unlock(&tp->lock);
++
++      if (counted && atomic_inc_return(&block->useswcnt) == 1)
++              static_branch_inc(&tcf_sw_enabled_key);
++#endif
+ }
+ static void tcf_chain_put(struct tcf_chain *chain);
+@@ -451,7 +444,7 @@ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
+                             bool sig_destroy, struct netlink_ext_ack *extack)
+ {
+       tp->ops->destroy(tp, rtnl_held, extack);
+-      tcf_block_filter_cnt_update(tp->chain->block, &tp->counted, false);
++      tcf_proto_count_usesw(tp, false);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
+       tcf_chain_put(tp->chain);
+@@ -2393,7 +2386,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
+               tfilter_notify(net, skb, n, tp, block, q, parent, fh,
+                              RTM_NEWTFILTER, false, rtnl_held, extack);
+               tfilter_put(tp, fh);
+-              tcf_block_filter_cnt_update(block, &tp->counted, true);
++              tcf_proto_count_usesw(tp, true);
+               /* q pointer is NULL for shared blocks */
+               if (q)
+                       q->flags &= ~TCQ_F_CAN_BYPASS;
+@@ -3515,8 +3508,6 @@ static void tcf_block_offload_inc(struct tcf_block *block, u32 *flags)
+       if (*flags & TCA_CLS_FLAGS_IN_HW)
+               return;
+       *flags |= TCA_CLS_FLAGS_IN_HW;
+-      if (tc_skip_sw(*flags))
+-              atomic_inc(&block->skipswcnt);
+       atomic_inc(&block->offloadcnt);
+ }
+@@ -3525,8 +3516,6 @@ static void tcf_block_offload_dec(struct tcf_block *block, u32 *flags)
+       if (!(*flags & TCA_CLS_FLAGS_IN_HW))
+               return;
+       *flags &= ~TCA_CLS_FLAGS_IN_HW;
+-      if (tc_skip_sw(*flags))
+-              atomic_dec(&block->skipswcnt);
+       atomic_dec(&block->offloadcnt);
+ }
+diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
+index d5a5dffcd6f9b..cede21257d27c 100644
+--- a/net/sched/cls_bpf.c
++++ b/net/sched/cls_bpf.c
+@@ -509,6 +509,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
+       if (!tc_in_hw(prog->gen_flags))
+               prog->gen_flags |= TCA_CLS_FLAGS_NOT_IN_HW;
++      tcf_proto_update_usesw(tp, prog->gen_flags);
++
+       if (oldprog) {
+               idr_replace(&head->handle_idr, prog, handle);
+               list_replace_rcu(&oldprog->link, &prog->link);
+diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
+index b00e491e8130d..4fc59af6696ea 100644
+--- a/net/sched/cls_flower.c
++++ b/net/sched/cls_flower.c
+@@ -2374,6 +2374,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
+       if (!tc_in_hw(fnew->flags))
+               fnew->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
++      tcf_proto_update_usesw(tp, fnew->flags);
++
+       spin_lock(&tp->lock);
+       /* tp was deleted concurrently. -EAGAIN will cause caller to lookup
+diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
+index c4ed11df62548..e8353b27c8c4d 100644
+--- a/net/sched/cls_matchall.c
++++ b/net/sched/cls_matchall.c
+@@ -228,6 +228,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
+       if (!tc_in_hw(new->flags))
+               new->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
++      tcf_proto_update_usesw(tp, new->flags);
++
+       *arg = head;
+       rcu_assign_pointer(tp->root, new);
+       return 0;
+diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
+index 1338d9b4c03a4..9829df127d054 100644
+--- a/net/sched/cls_u32.c
++++ b/net/sched/cls_u32.c
+@@ -950,6 +950,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
+               if (!tc_in_hw(new->flags))
+                       new->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
++              tcf_proto_update_usesw(tp, new->flags);
++
+               u32_replace_knode(tp, tp_c, new);
+               tcf_unbind_filter(tp, &n->res);
+               tcf_exts_get_net(&n->exts);
+@@ -1163,6 +1165,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
+               if (!tc_in_hw(n->flags))
+                       n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
++              tcf_proto_update_usesw(tp, n->flags);
++
+               ins = &ht->ht[TC_U32_HASH(handle)];
+               for (pins = rtnl_dereference(*ins); pins;
+                    ins = &pins->next, pins = rtnl_dereference(*ins))
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-6.6/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..990a2f0
--- /dev/null
@@ -0,0 +1,50 @@
+From 72ca602caf481109c4195ebae1a34141f18a32fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index ce9ee43e9ee2b..4331097f813ec 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1282,7 +1282,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ntohs(ipv6h_check->payload_len);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-6.6/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..a14dc2d
--- /dev/null
@@ -0,0 +1,57 @@
+From 9bb5cc8bb500be2675d14d6591f4b0c97de36de9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index 018ce8133b026..149d63cff667e 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1918,7 +1918,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch b/queue-6.6/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
new file mode 100644 (file)
index 0000000..9454979
--- /dev/null
@@ -0,0 +1,71 @@
+From 637bd3ade2324c39398731844bd537d8b2481390 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 09:07:01 +0200
+Subject: net/smc: fix TOCTOU race between smc_listen_out() and listener close
+
+From: Sidraya Jayagond <sidraya@linux.ibm.com>
+
+[ Upstream commit 185a4caeecabc150106deda1da170b09f2ad803f ]
+
+smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
+then acquires lock_sock_nested() only after the check passes. This
+opens a window where smc_close_active() can transition the listener
+to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
+queue, and release the lock, all between the lockless read and the
+delayed lock acquisition:
+
+  smc_listen_work (smc_hs_wq)          smc_close_active()
+  -------------------------------      -------------------------
+  release_sock(child)
+  if (sk_state == SMC_LISTEN) TRUE
+                                        lock_sock(listener)
+                                        sk_state = SMC_CLOSED
+                                        smc_close_cleanup_listen()
+                                        release_sock(listener)
+                                        flush_work(tcp_listen_work)
+  lock_sock_nested(listener)
+  smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
+
+smc_close_active() flushes only tcp_listen_work. Work items already
+dispatched onto smc_hs_wq for the CLC handshake continue running
+unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
+is never released, so the child smc_sock, its clcsock, and the
+reference all leak. A remote peer that opens TCP connections while the
+server calls close() can exhaust kernel memory.
+
+Move lock_sock_nested() to before the sk_state check so that the test
+and the enqueue are atomic under the listener lock.
+
+Fixes: fd57770dd198 ("net/smc: wait for pending work before clcsock release_sock")
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260803070701.126339-1-sidraya@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index e5e07160e5719..087102ff3c640 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1921,11 +1921,12 @@ static void smc_listen_out(struct smc_sock *new_smc)
+               atomic_dec(&lsmc->queued_smc_hs);
+       release_sock(newsmcsk); /* lock in smc_listen_work() */
++      lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+       if (lsmc->sk.sk_state == SMC_LISTEN) {
+-              lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+               smc_accept_enqueue(&lsmc->sk, newsmcsk);
+               release_sock(&lsmc->sk);
+       } else { /* no longer listening */
++              release_sock(&lsmc->sk);
+               smc_close_non_accepted(newsmcsk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-tcp-add-tcp-ao-config-and-structures.patch b/queue-6.6/net-tcp-add-tcp-ao-config-and-structures.patch
new file mode 100644 (file)
index 0000000..ce89c51
--- /dev/null
@@ -0,0 +1,217 @@
+From 9772224077b914196aa211675a40dc013bf3d8af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Oct 2023 20:21:54 +0100
+Subject: net/tcp: Add TCP-AO config and structures
+
+From: Dmitry Safonov <dima@arista.com>
+
+[ Upstream commit c845f5f3590ef4669fe5464f8a42be6442cd174b ]
+
+Introduce new kernel config option and common structures as well as
+helpers to be used by TCP-AO code.
+
+Co-developed-by: Francesco Ruggeri <fruggeri@arista.com>
+Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
+Co-developed-by: Salam Noureddine <noureddine@arista.com>
+Signed-off-by: Salam Noureddine <noureddine@arista.com>
+Signed-off-by: Dmitry Safonov <dima@arista.com>
+Acked-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: d0c80dbb9704 ("net/atm: fix slab-out-of-bounds read in vcc_setsockopt()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/tcp.h      |  9 +++-
+ include/net/tcp.h        |  8 +---
+ include/net/tcp_ao.h     | 90 ++++++++++++++++++++++++++++++++++++++++
+ include/uapi/linux/tcp.h |  2 +
+ net/ipv4/Kconfig         | 13 ++++++
+ 5 files changed, 114 insertions(+), 8 deletions(-)
+ create mode 100644 include/net/tcp_ao.h
+
+diff --git a/include/linux/tcp.h b/include/linux/tcp.h
+index e15452df9804f..c38778b0baa05 100644
+--- a/include/linux/tcp.h
++++ b/include/linux/tcp.h
+@@ -445,13 +445,18 @@ struct tcp_sock {
+       bool    syn_smc;        /* SYN includes SMC */
+ #endif
+-#ifdef CONFIG_TCP_MD5SIG
+-/* TCP AF-Specific parts; only used by MD5 Signature support so far */
++#if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO)
++/* TCP AF-Specific parts; only used by TCP-AO/MD5 Signature support so far */
+       const struct tcp_sock_af_ops    *af_specific;
++#ifdef CONFIG_TCP_MD5SIG
+ /* TCP MD5 Signature Option information */
+       struct tcp_md5sig_info  __rcu *md5sig_info;
+ #endif
++#ifdef CONFIG_TCP_AO
++      struct tcp_ao_info      __rcu *ao_info;
++#endif
++#endif
+ /* TCP fastopen related information */
+       struct tcp_fastopen_request *fastopen_req;
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 9c3ec3200e27b..0eb9341f74888 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -37,6 +37,7 @@
+ #include <net/snmp.h>
+ #include <net/ip.h>
+ #include <net/tcp_states.h>
++#include <net/tcp_ao.h>
+ #include <net/inet_ecn.h>
+ #include <net/dst.h>
+ #include <net/mptcp.h>
+@@ -1681,12 +1682,7 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp)
+       tp->retransmit_skb_hint = NULL;
+ }
+-union tcp_md5_addr {
+-      struct in_addr  a4;
+-#if IS_ENABLED(CONFIG_IPV6)
+-      struct in6_addr a6;
+-#endif
+-};
++#define tcp_md5_addr tcp_ao_addr
+ /* - key database */
+ struct tcp_md5sig_key {
+diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h
+new file mode 100644
+index 0000000000000..af76e1c47bea9
+--- /dev/null
++++ b/include/net/tcp_ao.h
+@@ -0,0 +1,90 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++#ifndef _TCP_AO_H
++#define _TCP_AO_H
++
++#define TCP_AO_KEY_ALIGN      1
++#define __tcp_ao_key_align __aligned(TCP_AO_KEY_ALIGN)
++
++union tcp_ao_addr {
++      struct in_addr  a4;
++#if IS_ENABLED(CONFIG_IPV6)
++      struct in6_addr a6;
++#endif
++};
++
++struct tcp_ao_hdr {
++      u8      kind;
++      u8      length;
++      u8      keyid;
++      u8      rnext_keyid;
++};
++
++struct tcp_ao_key {
++      struct hlist_node       node;
++      union tcp_ao_addr       addr;
++      u8                      key[TCP_AO_MAXKEYLEN] __tcp_ao_key_align;
++      unsigned int            tcp_sigpool_id;
++      unsigned int            digest_size;
++      u8                      prefixlen;
++      u8                      family;
++      u8                      keylen;
++      u8                      keyflags;
++      u8                      sndid;
++      u8                      rcvid;
++      u8                      maclen;
++      struct rcu_head         rcu;
++      u8                      traffic_keys[];
++};
++
++static inline u8 *rcv_other_key(struct tcp_ao_key *key)
++{
++      return key->traffic_keys;
++}
++
++static inline u8 *snd_other_key(struct tcp_ao_key *key)
++{
++      return key->traffic_keys + key->digest_size;
++}
++
++static inline int tcp_ao_maclen(const struct tcp_ao_key *key)
++{
++      return key->maclen;
++}
++
++static inline int tcp_ao_len(const struct tcp_ao_key *key)
++{
++      return tcp_ao_maclen(key) + sizeof(struct tcp_ao_hdr);
++}
++
++static inline unsigned int tcp_ao_digest_size(struct tcp_ao_key *key)
++{
++      return key->digest_size;
++}
++
++static inline int tcp_ao_sizeof_key(const struct tcp_ao_key *key)
++{
++      return sizeof(struct tcp_ao_key) + (key->digest_size << 1);
++}
++
++struct tcp_ao_info {
++      /* List of tcp_ao_key's */
++      struct hlist_head       head;
++      /* current_key and rnext_key aren't maintained on listen sockets.
++       * Their purpose is to cache keys on established connections,
++       * saving needless lookups. Never dereference any of them from
++       * listen sockets.
++       * ::current_key may change in RX to the key that was requested by
++       * the peer, please use READ_ONCE()/WRITE_ONCE() in order to avoid
++       * load/store tearing.
++       * Do the same for ::rnext_key, if you don't hold socket lock
++       * (it's changed only by userspace request in setsockopt()).
++       */
++      struct tcp_ao_key       *current_key;
++      struct tcp_ao_key       *rnext_key;
++      u32                     flags;
++      __be32                  lisn;
++      __be32                  risn;
++      struct rcu_head         rcu;
++};
++
++#endif /* _TCP_AO_H */
+diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
+index d1d08da6331ab..bf93a80809d6a 100644
+--- a/include/uapi/linux/tcp.h
++++ b/include/uapi/linux/tcp.h
+@@ -360,6 +360,8 @@ struct tcp_diag_md5sig {
+       __u8    tcpm_key[TCP_MD5SIG_MAXKEYLEN];
+ };
++#define TCP_AO_MAXKEYLEN      80
++
+ /* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */
+ #define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index 89e2ab023272f..8e94ed7c56a0e 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -744,6 +744,19 @@ config DEFAULT_TCP_CONG
+ config TCP_SIGPOOL
+       tristate
++config TCP_AO
++      bool "TCP: Authentication Option (RFC5925)"
++      select CRYPTO
++      select TCP_SIGPOOL
++      depends on 64BIT && IPV6 != m # seq-number extension needs WRITE_ONCE(u64)
++      help
++        TCP-AO specifies the use of stronger Message Authentication Codes (MACs),
++        protects against replays for long-lived TCP connections, and
++        provides more details on the association of security with TCP
++        connections than TCP MD5 (See RFC5925)
++
++        If unsure, say N.
++
+ config TCP_MD5SIG
+       bool "TCP: MD5 Signature Option support (RFC2385)"
+       select CRYPTO
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-tcp-prepare-tcp_md5sig_pool-for-tcp-ao.patch b/queue-6.6/net-tcp-prepare-tcp_md5sig_pool-for-tcp-ao.patch
new file mode 100644 (file)
index 0000000..374e590
--- /dev/null
@@ -0,0 +1,1081 @@
+From 8917d63c7fb7265415692a74297683511f001bee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Oct 2023 20:21:53 +0100
+Subject: net/tcp: Prepare tcp_md5sig_pool for TCP-AO
+
+From: Dmitry Safonov <dima@arista.com>
+
+[ Upstream commit 8c73b26315aadb82218360d0a9a05e515f6e4118 ]
+
+TCP-AO, similarly to TCP-MD5, needs to allocate tfms on a slow-path,
+which is setsockopt() and use crypto ahash requests on fast paths,
+which are RX/TX softirqs. Also, it needs a temporary/scratch buffer
+for preparing the hash.
+
+Rework tcp_md5sig_pool in order to support other hashing algorithms
+than MD5. It will make it possible to share pre-allocated crypto_ahash
+descriptors and scratch area between all TCP hash users.
+
+Internally tcp_sigpool calls crypto_clone_ahash() API over pre-allocated
+crypto ahash tfm. Kudos to Herbert, who provided this new crypto API.
+
+I was a little concerned over GFP_ATOMIC allocations of ahash and
+crypto_request in RX/TX (see tcp_sigpool_start()), so I benchmarked both
+"backends" with different algorithms, using patched version of iperf3[2].
+On my laptop with i7-7600U @ 2.80GHz:
+
+                         clone-tfm                per-CPU-requests
+TCP-MD5                  2.25 Gbits/sec           2.30 Gbits/sec
+TCP-AO(hmac(sha1))       2.53 Gbits/sec           2.54 Gbits/sec
+TCP-AO(hmac(sha512))     1.67 Gbits/sec           1.64 Gbits/sec
+TCP-AO(hmac(sha384))     1.77 Gbits/sec           1.80 Gbits/sec
+TCP-AO(hmac(sha224))     1.29 Gbits/sec           1.30 Gbits/sec
+TCP-AO(hmac(sha3-512))    481 Mbits/sec            480 Mbits/sec
+TCP-AO(hmac(md5))        2.07 Gbits/sec           2.12 Gbits/sec
+TCP-AO(hmac(rmd160))     1.01 Gbits/sec            995 Mbits/sec
+TCP-AO(cmac(aes128))     [not supporetd yet]      2.11 Gbits/sec
+
+So, it seems that my concerns don't have strong grounds and per-CPU
+crypto_request allocation can be dropped/removed from tcp_sigpool once
+ciphers get crypto_clone_ahash() support.
+
+[1]: https://lore.kernel.org/all/ZDefxOq6Ax0JeTRH@gondor.apana.org.au/T/#u
+[2]: https://github.com/0x7f454c46/iperf/tree/tcp-md5-ao
+Signed-off-by: Dmitry Safonov <dima@arista.com>
+Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
+Acked-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: d0c80dbb9704 ("net/atm: fix slab-out-of-bounds read in vcc_setsockopt()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tcp.h        |  50 ++++--
+ net/ipv4/Kconfig         |   4 +
+ net/ipv4/Makefile        |   1 +
+ net/ipv4/tcp.c           | 145 +++-------------
+ net/ipv4/tcp_ipv4.c      |  97 ++++++-----
+ net/ipv4/tcp_minisocks.c |  21 ++-
+ net/ipv4/tcp_sigpool.c   | 358 +++++++++++++++++++++++++++++++++++++++
+ net/ipv6/tcp_ipv6.c      |  60 +++----
+ 8 files changed, 525 insertions(+), 211 deletions(-)
+ create mode 100644 net/ipv4/tcp_sigpool.c
+
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index a6def0aab3ed3..9c3ec3200e27b 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -1730,12 +1730,39 @@ union tcp_md5sum_block {
+ #endif
+ };
+-/* - pool: digest algorithm, hash description and scratch buffer */
+-struct tcp_md5sig_pool {
+-      struct ahash_request    *md5_req;
+-      void                    *scratch;
++/*
++ * struct tcp_sigpool - per-CPU pool of ahash_requests
++ * @scratch: per-CPU temporary area, that can be used between
++ *         tcp_sigpool_start() and tcp_sigpool_end() to perform
++ *         crypto request
++ * @req: pre-allocated ahash request
++ */
++struct tcp_sigpool {
++      void *scratch;
++      struct ahash_request *req;
+ };
++int tcp_sigpool_alloc_ahash(const char *alg, size_t scratch_size);
++void tcp_sigpool_get(unsigned int id);
++void tcp_sigpool_release(unsigned int id);
++int tcp_sigpool_hash_skb_data(struct tcp_sigpool *hp,
++                            const struct sk_buff *skb,
++                            unsigned int header_len);
++
++/**
++ * tcp_sigpool_start - disable bh and start using tcp_sigpool_ahash
++ * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_ahash()
++ * @c: returned tcp_sigpool for usage (uninitialized on failure)
++ *
++ * Returns 0 on success, error otherwise.
++ */
++int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c);
++/**
++ * tcp_sigpool_end - enable bh and stop using tcp_sigpool
++ * @c: tcp_sigpool context that was returned by tcp_sigpool_start()
++ */
++void tcp_sigpool_end(struct tcp_sigpool *c);
++size_t tcp_sigpool_algo(unsigned int id, char *buf, size_t buf_len);
+ /* - functions */
+ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
+                       const struct sock *sk, const struct sk_buff *skb);
+@@ -1791,17 +1818,12 @@ tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,
+ #define tcp_twsk_md5_key(twsk)        NULL
+ #endif
+-bool tcp_alloc_md5sig_pool(void);
+-
+-struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
+-static inline void tcp_put_md5sig_pool(void)
+-{
+-      local_bh_enable();
+-}
++int tcp_md5_alloc_sigpool(void);
++void tcp_md5_release_sigpool(void);
++void tcp_md5_add_sigpool(void);
++extern int tcp_md5_sigpool_id;
+-int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *,
+-                        unsigned int header_len);
+-int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
++int tcp_md5_hash_key(struct tcp_sigpool *hp,
+                    const struct tcp_md5sig_key *key);
+ /* From tcp_fastopen.c */
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index 2dfb12230f089..89e2ab023272f 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -741,10 +741,14 @@ config DEFAULT_TCP_CONG
+       default "bbr" if DEFAULT_BBR
+       default "cubic"
++config TCP_SIGPOOL
++      tristate
++
+ config TCP_MD5SIG
+       bool "TCP: MD5 Signature Option support (RFC2385)"
+       select CRYPTO
+       select CRYPTO_MD5
++      select TCP_SIGPOOL
+       help
+         RFC2385 specifies a method of giving MD5 protection to TCP sessions.
+         Its main (only?) use is to protect BGP sessions between core routers
+diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
+index b18ba8ef93ad2..cd760793cfcba 100644
+--- a/net/ipv4/Makefile
++++ b/net/ipv4/Makefile
+@@ -62,6 +62,7 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
+ obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
+ obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
++obj-$(CONFIG_TCP_SIGPOOL) += tcp_sigpool.o
+ obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o
+ obj-$(CONFIG_BPF_SYSCALL) += udp_bpf.o
+ obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 5b1fbb0ca2ff6..f05d1699683ff 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -4365,141 +4365,52 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
+ EXPORT_SYMBOL(tcp_getsockopt);
+ #ifdef CONFIG_TCP_MD5SIG
+-static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool);
+-static DEFINE_MUTEX(tcp_md5sig_mutex);
+-static bool tcp_md5sig_pool_populated = false;
++int tcp_md5_sigpool_id = -1;
++EXPORT_SYMBOL_GPL(tcp_md5_sigpool_id);
+-static void __tcp_alloc_md5sig_pool(void)
++int tcp_md5_alloc_sigpool(void)
+ {
+-      struct crypto_ahash *hash;
+-      int cpu;
+-
+-      hash = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
+-      if (IS_ERR(hash))
+-              return;
+-
+-      for_each_possible_cpu(cpu) {
+-              void *scratch = per_cpu(tcp_md5sig_pool, cpu).scratch;
+-              struct ahash_request *req;
+-
+-              if (!scratch) {
+-                      scratch = kmalloc_node(sizeof(union tcp_md5sum_block) +
+-                                             sizeof(struct tcphdr),
+-                                             GFP_KERNEL,
+-                                             cpu_to_node(cpu));
+-                      if (!scratch)
+-                              return;
+-                      per_cpu(tcp_md5sig_pool, cpu).scratch = scratch;
+-              }
+-              if (per_cpu(tcp_md5sig_pool, cpu).md5_req)
+-                      continue;
+-
+-              req = ahash_request_alloc(hash, GFP_KERNEL);
+-              if (!req)
+-                      return;
+-
+-              ahash_request_set_callback(req, 0, NULL, NULL);
+-
+-              per_cpu(tcp_md5sig_pool, cpu).md5_req = req;
+-      }
+-      /* before setting tcp_md5sig_pool_populated, we must commit all writes
+-       * to memory. See smp_rmb() in tcp_get_md5sig_pool()
+-       */
+-      smp_wmb();
+-      /* Paired with READ_ONCE() from tcp_alloc_md5sig_pool()
+-       * and tcp_get_md5sig_pool().
+-      */
+-      WRITE_ONCE(tcp_md5sig_pool_populated, true);
+-}
+-
+-bool tcp_alloc_md5sig_pool(void)
+-{
+-      /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */
+-      if (unlikely(!READ_ONCE(tcp_md5sig_pool_populated))) {
+-              mutex_lock(&tcp_md5sig_mutex);
+-
+-              if (!tcp_md5sig_pool_populated)
+-                      __tcp_alloc_md5sig_pool();
++      size_t scratch_size;
++      int ret;
+-              mutex_unlock(&tcp_md5sig_mutex);
++      scratch_size = sizeof(union tcp_md5sum_block) + sizeof(struct tcphdr);
++      ret = tcp_sigpool_alloc_ahash("md5", scratch_size);
++      if (ret >= 0) {
++              /* As long as any md5 sigpool was allocated, the return
++               * id would stay the same. Re-write the id only for the case
++               * when previously all MD5 keys were deleted and this call
++               * allocates the first MD5 key, which may return a different
++               * sigpool id than was used previously.
++               */
++              WRITE_ONCE(tcp_md5_sigpool_id, ret); /* Avoids the compiler potentially being smart here */
++              return 0;
+       }
+-      /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */
+-      return READ_ONCE(tcp_md5sig_pool_populated);
++      return ret;
+ }
+-EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
+-
+-/**
+- *    tcp_get_md5sig_pool - get md5sig_pool for this user
+- *
+- *    We use percpu structure, so if we succeed, we exit with preemption
+- *    and BH disabled, to make sure another thread or softirq handling
+- *    wont try to get same context.
+- */
+-struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
++void tcp_md5_release_sigpool(void)
+ {
+-      local_bh_disable();
+-
+-      /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */
+-      if (READ_ONCE(tcp_md5sig_pool_populated)) {
+-              /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */
+-              smp_rmb();
+-              return this_cpu_ptr(&tcp_md5sig_pool);
+-      }
+-      local_bh_enable();
+-      return NULL;
++      tcp_sigpool_release(READ_ONCE(tcp_md5_sigpool_id));
+ }
+-EXPORT_SYMBOL(tcp_get_md5sig_pool);
+-int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
+-                        const struct sk_buff *skb, unsigned int header_len)
++void tcp_md5_add_sigpool(void)
+ {
+-      struct scatterlist sg;
+-      const struct tcphdr *tp = tcp_hdr(skb);
+-      struct ahash_request *req = hp->md5_req;
+-      unsigned int i;
+-      const unsigned int head_data_len = skb_headlen(skb) > header_len ?
+-                                         skb_headlen(skb) - header_len : 0;
+-      const struct skb_shared_info *shi = skb_shinfo(skb);
+-      struct sk_buff *frag_iter;
+-
+-      sg_init_table(&sg, 1);
+-
+-      sg_set_buf(&sg, ((u8 *) tp) + header_len, head_data_len);
+-      ahash_request_set_crypt(req, &sg, NULL, head_data_len);
+-      if (crypto_ahash_update(req))
+-              return 1;
+-
+-      for (i = 0; i < shi->nr_frags; ++i) {
+-              const skb_frag_t *f = &shi->frags[i];
+-              unsigned int offset = skb_frag_off(f);
+-              struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
+-
+-              sg_set_page(&sg, page, skb_frag_size(f),
+-                          offset_in_page(offset));
+-              ahash_request_set_crypt(req, &sg, NULL, skb_frag_size(f));
+-              if (crypto_ahash_update(req))
+-                      return 1;
+-      }
+-
+-      skb_walk_frags(skb, frag_iter)
+-              if (tcp_md5_hash_skb_data(hp, frag_iter, 0))
+-                      return 1;
+-
+-      return 0;
++      tcp_sigpool_get(READ_ONCE(tcp_md5_sigpool_id));
+ }
+-EXPORT_SYMBOL(tcp_md5_hash_skb_data);
+-int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, const struct tcp_md5sig_key *key)
++int tcp_md5_hash_key(struct tcp_sigpool *hp,
++                   const struct tcp_md5sig_key *key)
+ {
+       u8 keylen = READ_ONCE(key->keylen); /* paired with WRITE_ONCE() in tcp_md5_do_add */
+       struct scatterlist sg;
+       sg_init_one(&sg, key->key, keylen);
+-      ahash_request_set_crypt(hp->md5_req, &sg, NULL, keylen);
++      ahash_request_set_crypt(hp->req, &sg, NULL, keylen);
+-      /* We use data_race() because tcp_md5_do_add() might change key->key under us */
+-      return data_race(crypto_ahash_update(hp->md5_req));
++      /* We use data_race() because tcp_md5_do_add() might change
++       * key->key under us
++       */
++      return data_race(crypto_ahash_update(hp->req));
+ }
+ EXPORT_SYMBOL(tcp_md5_hash_key);
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 868a593d63ad2..0255f149885eb 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -1227,10 +1227,6 @@ static int __tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
+       key = sock_kmalloc(sk, sizeof(*key), gfp | __GFP_ZERO);
+       if (!key)
+               return -ENOMEM;
+-      if (!tcp_alloc_md5sig_pool()) {
+-              sock_kfree_s(sk, key, sizeof(*key));
+-              return -ENOMEM;
+-      }
+       memcpy(key->key, newkey, newkeylen);
+       key->keylen = newkeylen;
+@@ -1252,8 +1248,13 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
+       struct tcp_sock *tp = tcp_sk(sk);
+       if (!rcu_dereference_protected(tp->md5sig_info, lockdep_sock_is_held(sk))) {
+-              if (tcp_md5sig_info_add(sk, GFP_KERNEL))
++              if (tcp_md5_alloc_sigpool())
++                      return -ENOMEM;
++
++              if (tcp_md5sig_info_add(sk, GFP_KERNEL)) {
++                      tcp_md5_release_sigpool();
+                       return -ENOMEM;
++              }
+               if (!static_branch_inc(&tcp_md5_needed.key)) {
+                       struct tcp_md5sig_info *md5sig;
+@@ -1261,6 +1262,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
+                       md5sig = rcu_dereference_protected(tp->md5sig_info, lockdep_sock_is_held(sk));
+                       rcu_assign_pointer(tp->md5sig_info, NULL);
+                       kfree_rcu(md5sig, rcu);
++                      tcp_md5_release_sigpool();
+                       return -EUSERS;
+               }
+       }
+@@ -1277,8 +1279,12 @@ int tcp_md5_key_copy(struct sock *sk, const union tcp_md5_addr *addr,
+       struct tcp_sock *tp = tcp_sk(sk);
+       if (!rcu_dereference_protected(tp->md5sig_info, lockdep_sock_is_held(sk))) {
+-              if (tcp_md5sig_info_add(sk, sk_gfp_mask(sk, GFP_ATOMIC)))
++              tcp_md5_add_sigpool();
++
++              if (tcp_md5sig_info_add(sk, sk_gfp_mask(sk, GFP_ATOMIC))) {
++                      tcp_md5_release_sigpool();
+                       return -ENOMEM;
++              }
+               if (!static_key_fast_inc_not_disabled(&tcp_md5_needed.key.key)) {
+                       struct tcp_md5sig_info *md5sig;
+@@ -1287,6 +1293,7 @@ int tcp_md5_key_copy(struct sock *sk, const union tcp_md5_addr *addr,
+                       net_warn_ratelimited("Too many TCP-MD5 keys in the system\n");
+                       rcu_assign_pointer(tp->md5sig_info, NULL);
+                       kfree_rcu(md5sig, rcu);
++                      tcp_md5_release_sigpool();
+                       return -EUSERS;
+               }
+       }
+@@ -1386,7 +1393,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, int optname,
+                             cmd.tcpm_key, cmd.tcpm_keylen);
+ }
+-static int tcp_v4_md5_hash_headers(struct tcp_md5sig_pool *hp,
++static int tcp_v4_md5_hash_headers(struct tcp_sigpool *hp,
+                                  __be32 daddr, __be32 saddr,
+                                  const struct tcphdr *th, int nbytes)
+ {
+@@ -1406,38 +1413,35 @@ static int tcp_v4_md5_hash_headers(struct tcp_md5sig_pool *hp,
+       _th->check = 0;
+       sg_init_one(&sg, bp, sizeof(*bp) + sizeof(*th));
+-      ahash_request_set_crypt(hp->md5_req, &sg, NULL,
++      ahash_request_set_crypt(hp->req, &sg, NULL,
+                               sizeof(*bp) + sizeof(*th));
+-      return crypto_ahash_update(hp->md5_req);
++      return crypto_ahash_update(hp->req);
+ }
+ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
+                              __be32 daddr, __be32 saddr, const struct tcphdr *th)
+ {
+-      struct tcp_md5sig_pool *hp;
+-      struct ahash_request *req;
++      struct tcp_sigpool hp;
+-      hp = tcp_get_md5sig_pool();
+-      if (!hp)
+-              goto clear_hash_noput;
+-      req = hp->md5_req;
++      if (tcp_sigpool_start(tcp_md5_sigpool_id, &hp))
++              goto clear_hash_nostart;
+-      if (crypto_ahash_init(req))
++      if (crypto_ahash_init(hp.req))
+               goto clear_hash;
+-      if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, th->doff << 2))
++      if (tcp_v4_md5_hash_headers(&hp, daddr, saddr, th, th->doff << 2))
+               goto clear_hash;
+-      if (tcp_md5_hash_key(hp, key))
++      if (tcp_md5_hash_key(&hp, key))
+               goto clear_hash;
+-      ahash_request_set_crypt(req, NULL, md5_hash, 0);
+-      if (crypto_ahash_final(req))
++      ahash_request_set_crypt(hp.req, NULL, md5_hash, 0);
++      if (crypto_ahash_final(hp.req))
+               goto clear_hash;
+-      tcp_put_md5sig_pool();
++      tcp_sigpool_end(&hp);
+       return 0;
+ clear_hash:
+-      tcp_put_md5sig_pool();
+-clear_hash_noput:
++      tcp_sigpool_end(&hp);
++clear_hash_nostart:
+       memset(md5_hash, 0, 16);
+       return 1;
+ }
+@@ -1446,9 +1450,8 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
+                       const struct sock *sk,
+                       const struct sk_buff *skb)
+ {
+-      struct tcp_md5sig_pool *hp;
+-      struct ahash_request *req;
+       const struct tcphdr *th = tcp_hdr(skb);
++      struct tcp_sigpool hp;
+       __be32 saddr, daddr;
+       if (sk) { /* valid for establish/request sockets */
+@@ -1460,30 +1463,28 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
+               daddr = iph->daddr;
+       }
+-      hp = tcp_get_md5sig_pool();
+-      if (!hp)
+-              goto clear_hash_noput;
+-      req = hp->md5_req;
++      if (tcp_sigpool_start(tcp_md5_sigpool_id, &hp))
++              goto clear_hash_nostart;
+-      if (crypto_ahash_init(req))
++      if (crypto_ahash_init(hp.req))
+               goto clear_hash;
+-      if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, skb->len))
++      if (tcp_v4_md5_hash_headers(&hp, daddr, saddr, th, skb->len))
+               goto clear_hash;
+-      if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
++      if (tcp_sigpool_hash_skb_data(&hp, skb, th->doff << 2))
+               goto clear_hash;
+-      if (tcp_md5_hash_key(hp, key))
++      if (tcp_md5_hash_key(&hp, key))
+               goto clear_hash;
+-      ahash_request_set_crypt(req, NULL, md5_hash, 0);
+-      if (crypto_ahash_final(req))
++      ahash_request_set_crypt(hp.req, NULL, md5_hash, 0);
++      if (crypto_ahash_final(hp.req))
+               goto clear_hash;
+-      tcp_put_md5sig_pool();
++      tcp_sigpool_end(&hp);
+       return 0;
+ clear_hash:
+-      tcp_put_md5sig_pool();
+-clear_hash_noput:
++      tcp_sigpool_end(&hp);
++clear_hash_nostart:
+       memset(md5_hash, 0, 16);
+       return 1;
+ }
+@@ -2311,6 +2312,18 @@ static int tcp_v4_init_sock(struct sock *sk)
+       return 0;
+ }
++#ifdef CONFIG_TCP_MD5SIG
++static void tcp_md5sig_info_free_rcu(struct rcu_head *head)
++{
++      struct tcp_md5sig_info *md5sig;
++
++      md5sig = container_of(head, struct tcp_md5sig_info, rcu);
++      kfree(md5sig);
++      static_branch_slow_dec_deferred(&tcp_md5_needed);
++      tcp_md5_release_sigpool();
++}
++#endif
++
+ void tcp_v4_destroy_sock(struct sock *sk)
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+@@ -2335,10 +2348,12 @@ void tcp_v4_destroy_sock(struct sock *sk)
+ #ifdef CONFIG_TCP_MD5SIG
+       /* Clean up the MD5 key list, if any */
+       if (tp->md5sig_info) {
++              struct tcp_md5sig_info *md5sig;
++
++              md5sig = rcu_dereference_protected(tp->md5sig_info, 1);
+               tcp_clear_md5_list(sk);
+-              kfree_rcu(rcu_dereference_protected(tp->md5sig_info, 1), rcu);
+-              tp->md5sig_info = NULL;
+-              static_branch_slow_dec_deferred(&tcp_md5_needed);
++              call_rcu(&md5sig->rcu, tcp_md5sig_info_free_rcu);
++              rcu_assign_pointer(tp->md5sig_info, NULL);
+       }
+ #endif
+diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
+index 2eea9672ca01e..c3f5e4fc7b210 100644
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -261,10 +261,9 @@ static void tcp_time_wait_init(struct sock *sk, struct tcp_timewait_sock *tcptw)
+               tcptw->tw_md5_key = kmemdup(key, sizeof(*key), GFP_ATOMIC);
+               if (!tcptw->tw_md5_key)
+                       return;
+-              if (!tcp_alloc_md5sig_pool())
+-                      goto out_free;
+               if (!static_key_fast_inc_not_disabled(&tcp_md5_needed.key.key))
+                       goto out_free;
++              tcp_md5_add_sigpool();
+       }
+       return;
+ out_free:
+@@ -348,16 +347,26 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
+ }
+ EXPORT_SYMBOL(tcp_time_wait);
++#ifdef CONFIG_TCP_MD5SIG
++static void tcp_md5_twsk_free_rcu(struct rcu_head *head)
++{
++      struct tcp_md5sig_key *key;
++
++      key = container_of(head, struct tcp_md5sig_key, rcu);
++      kfree(key);
++      static_branch_slow_dec_deferred(&tcp_md5_needed);
++      tcp_md5_release_sigpool();
++}
++#endif
++
+ void tcp_twsk_destructor(struct sock *sk)
+ {
+ #ifdef CONFIG_TCP_MD5SIG
+       if (static_branch_unlikely(&tcp_md5_needed.key)) {
+               struct tcp_timewait_sock *twsk = tcp_twsk(sk);
+-              if (twsk->tw_md5_key) {
+-                      kfree_rcu(twsk->tw_md5_key, rcu);
+-                      static_branch_slow_dec_deferred(&tcp_md5_needed);
+-              }
++              if (twsk->tw_md5_key)
++                      call_rcu(&twsk->tw_md5_key->rcu, tcp_md5_twsk_free_rcu);
+       }
+ #endif
+ }
+diff --git a/net/ipv4/tcp_sigpool.c b/net/ipv4/tcp_sigpool.c
+new file mode 100644
+index 0000000000000..65a8eaae2fec6
+--- /dev/null
++++ b/net/ipv4/tcp_sigpool.c
+@@ -0,0 +1,358 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#include <crypto/hash.h>
++#include <linux/cpu.h>
++#include <linux/kref.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/percpu.h>
++#include <linux/workqueue.h>
++#include <net/tcp.h>
++
++static size_t __scratch_size;
++static DEFINE_PER_CPU(void __rcu *, sigpool_scratch);
++
++struct sigpool_entry {
++      struct crypto_ahash     *hash;
++      const char              *alg;
++      struct kref             kref;
++      uint16_t                needs_key:1,
++                              reserved:15;
++};
++
++#define CPOOL_SIZE (PAGE_SIZE / sizeof(struct sigpool_entry))
++static struct sigpool_entry cpool[CPOOL_SIZE];
++static unsigned int cpool_populated;
++static DEFINE_MUTEX(cpool_mutex);
++
++/* Slow-path */
++struct scratches_to_free {
++      struct rcu_head rcu;
++      unsigned int cnt;
++      void *scratches[];
++};
++
++static void free_old_scratches(struct rcu_head *head)
++{
++      struct scratches_to_free *stf;
++
++      stf = container_of(head, struct scratches_to_free, rcu);
++      while (stf->cnt--)
++              kfree(stf->scratches[stf->cnt]);
++      kfree(stf);
++}
++
++/**
++ * sigpool_reserve_scratch - re-allocates scratch buffer, slow-path
++ * @size: request size for the scratch/temp buffer
++ */
++static int sigpool_reserve_scratch(size_t size)
++{
++      struct scratches_to_free *stf;
++      size_t stf_sz = struct_size(stf, scratches, num_possible_cpus());
++      int cpu, err = 0;
++
++      lockdep_assert_held(&cpool_mutex);
++      if (__scratch_size >= size)
++              return 0;
++
++      stf = kmalloc(stf_sz, GFP_KERNEL);
++      if (!stf)
++              return -ENOMEM;
++      stf->cnt = 0;
++
++      size = max(size, __scratch_size);
++      cpus_read_lock();
++      for_each_possible_cpu(cpu) {
++              void *scratch, *old_scratch;
++
++              scratch = kmalloc_node(size, GFP_KERNEL, cpu_to_node(cpu));
++              if (!scratch) {
++                      err = -ENOMEM;
++                      break;
++              }
++
++              old_scratch = rcu_replace_pointer(per_cpu(sigpool_scratch, cpu),
++                                      scratch, lockdep_is_held(&cpool_mutex));
++              if (!cpu_online(cpu) || !old_scratch) {
++                      kfree(old_scratch);
++                      continue;
++              }
++              stf->scratches[stf->cnt++] = old_scratch;
++      }
++      cpus_read_unlock();
++      if (!err)
++              __scratch_size = size;
++
++      call_rcu(&stf->rcu, free_old_scratches);
++      return err;
++}
++
++static void sigpool_scratch_free(void)
++{
++      int cpu;
++
++      for_each_possible_cpu(cpu)
++              kfree(rcu_replace_pointer(per_cpu(sigpool_scratch, cpu),
++                                        NULL, lockdep_is_held(&cpool_mutex)));
++      __scratch_size = 0;
++}
++
++static int __cpool_try_clone(struct crypto_ahash *hash)
++{
++      struct crypto_ahash *tmp;
++
++      tmp = crypto_clone_ahash(hash);
++      if (IS_ERR(tmp))
++              return PTR_ERR(tmp);
++
++      crypto_free_ahash(tmp);
++      return 0;
++}
++
++static int __cpool_alloc_ahash(struct sigpool_entry *e, const char *alg)
++{
++      struct crypto_ahash *cpu0_hash;
++      int ret;
++
++      e->alg = kstrdup(alg, GFP_KERNEL);
++      if (!e->alg)
++              return -ENOMEM;
++
++      cpu0_hash = crypto_alloc_ahash(alg, 0, CRYPTO_ALG_ASYNC);
++      if (IS_ERR(cpu0_hash)) {
++              ret = PTR_ERR(cpu0_hash);
++              goto out_free_alg;
++      }
++
++      e->needs_key = crypto_ahash_get_flags(cpu0_hash) & CRYPTO_TFM_NEED_KEY;
++
++      ret = __cpool_try_clone(cpu0_hash);
++      if (ret)
++              goto out_free_cpu0_hash;
++      e->hash = cpu0_hash;
++      kref_init(&e->kref);
++      return 0;
++
++out_free_cpu0_hash:
++      crypto_free_ahash(cpu0_hash);
++out_free_alg:
++      kfree(e->alg);
++      e->alg = NULL;
++      return ret;
++}
++
++/**
++ * tcp_sigpool_alloc_ahash - allocates pool for ahash requests
++ * @alg: name of async hash algorithm
++ * @scratch_size: reserve a tcp_sigpool::scratch buffer of this size
++ */
++int tcp_sigpool_alloc_ahash(const char *alg, size_t scratch_size)
++{
++      int i, ret;
++
++      /* slow-path */
++      mutex_lock(&cpool_mutex);
++      ret = sigpool_reserve_scratch(scratch_size);
++      if (ret)
++              goto out;
++      for (i = 0; i < cpool_populated; i++) {
++              if (!cpool[i].alg)
++                      continue;
++              if (strcmp(cpool[i].alg, alg))
++                      continue;
++
++              if (kref_read(&cpool[i].kref) > 0)
++                      kref_get(&cpool[i].kref);
++              else
++                      kref_init(&cpool[i].kref);
++              ret = i;
++              goto out;
++      }
++
++      for (i = 0; i < cpool_populated; i++) {
++              if (!cpool[i].alg)
++                      break;
++      }
++      if (i >= CPOOL_SIZE) {
++              ret = -ENOSPC;
++              goto out;
++      }
++
++      ret = __cpool_alloc_ahash(&cpool[i], alg);
++      if (!ret) {
++              ret = i;
++              if (i == cpool_populated)
++                      cpool_populated++;
++      }
++out:
++      mutex_unlock(&cpool_mutex);
++      return ret;
++}
++EXPORT_SYMBOL_GPL(tcp_sigpool_alloc_ahash);
++
++static void __cpool_free_entry(struct sigpool_entry *e)
++{
++      crypto_free_ahash(e->hash);
++      kfree(e->alg);
++      memset(e, 0, sizeof(*e));
++}
++
++static void cpool_cleanup_work_cb(struct work_struct *work)
++{
++      bool free_scratch = true;
++      unsigned int i;
++
++      mutex_lock(&cpool_mutex);
++      for (i = 0; i < cpool_populated; i++) {
++              if (kref_read(&cpool[i].kref) > 0) {
++                      free_scratch = false;
++                      continue;
++              }
++              if (!cpool[i].alg)
++                      continue;
++              __cpool_free_entry(&cpool[i]);
++      }
++      if (free_scratch)
++              sigpool_scratch_free();
++      mutex_unlock(&cpool_mutex);
++}
++
++static DECLARE_WORK(cpool_cleanup_work, cpool_cleanup_work_cb);
++static void cpool_schedule_cleanup(struct kref *kref)
++{
++      schedule_work(&cpool_cleanup_work);
++}
++
++/**
++ * tcp_sigpool_release - decreases number of users for a pool. If it was
++ * the last user of the pool, releases any memory that was consumed.
++ * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_ahash()
++ */
++void tcp_sigpool_release(unsigned int id)
++{
++      if (WARN_ON_ONCE(id > cpool_populated || !cpool[id].alg))
++              return;
++
++      /* slow-path */
++      kref_put(&cpool[id].kref, cpool_schedule_cleanup);
++}
++EXPORT_SYMBOL_GPL(tcp_sigpool_release);
++
++/**
++ * tcp_sigpool_get - increases number of users (refcounter) for a pool
++ * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_ahash()
++ */
++void tcp_sigpool_get(unsigned int id)
++{
++      if (WARN_ON_ONCE(id > cpool_populated || !cpool[id].alg))
++              return;
++      kref_get(&cpool[id].kref);
++}
++EXPORT_SYMBOL_GPL(tcp_sigpool_get);
++
++int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(RCU_BH)
++{
++      struct crypto_ahash *hash;
++
++      rcu_read_lock_bh();
++      if (WARN_ON_ONCE(id > cpool_populated || !cpool[id].alg)) {
++              rcu_read_unlock_bh();
++              return -EINVAL;
++      }
++
++      hash = crypto_clone_ahash(cpool[id].hash);
++      if (IS_ERR(hash)) {
++              rcu_read_unlock_bh();
++              return PTR_ERR(hash);
++      }
++
++      c->req = ahash_request_alloc(hash, GFP_ATOMIC);
++      if (!c->req) {
++              crypto_free_ahash(hash);
++              rcu_read_unlock_bh();
++              return -ENOMEM;
++      }
++      ahash_request_set_callback(c->req, 0, NULL, NULL);
++
++      /* Pairs with tcp_sigpool_reserve_scratch(), scratch area is
++       * valid (allocated) until tcp_sigpool_end().
++       */
++      c->scratch = rcu_dereference_bh(*this_cpu_ptr(&sigpool_scratch));
++      return 0;
++}
++EXPORT_SYMBOL_GPL(tcp_sigpool_start);
++
++void tcp_sigpool_end(struct tcp_sigpool *c) __releases(RCU_BH)
++{
++      struct crypto_ahash *hash = crypto_ahash_reqtfm(c->req);
++
++      rcu_read_unlock_bh();
++      ahash_request_free(c->req);
++      crypto_free_ahash(hash);
++}
++EXPORT_SYMBOL_GPL(tcp_sigpool_end);
++
++/**
++ * tcp_sigpool_algo - return algorithm of tcp_sigpool
++ * @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_ahash()
++ * @buf: buffer to return name of algorithm
++ * @buf_len: size of @buf
++ */
++size_t tcp_sigpool_algo(unsigned int id, char *buf, size_t buf_len)
++{
++      if (WARN_ON_ONCE(id > cpool_populated || !cpool[id].alg))
++              return -EINVAL;
++
++      return strscpy(buf, cpool[id].alg, buf_len);
++}
++EXPORT_SYMBOL_GPL(tcp_sigpool_algo);
++
++/**
++ * tcp_sigpool_hash_skb_data - hash data in skb with initialized tcp_sigpool
++ * @hp: tcp_sigpool pointer
++ * @skb: buffer to add sign for
++ * @header_len: TCP header length for this segment
++ */
++int tcp_sigpool_hash_skb_data(struct tcp_sigpool *hp,
++                            const struct sk_buff *skb,
++                            unsigned int header_len)
++{
++      const unsigned int head_data_len = skb_headlen(skb) > header_len ?
++                                         skb_headlen(skb) - header_len : 0;
++      const struct skb_shared_info *shi = skb_shinfo(skb);
++      const struct tcphdr *tp = tcp_hdr(skb);
++      struct ahash_request *req = hp->req;
++      struct sk_buff *frag_iter;
++      struct scatterlist sg;
++      unsigned int i;
++
++      sg_init_table(&sg, 1);
++
++      sg_set_buf(&sg, ((u8 *)tp) + header_len, head_data_len);
++      ahash_request_set_crypt(req, &sg, NULL, head_data_len);
++      if (crypto_ahash_update(req))
++              return 1;
++
++      for (i = 0; i < shi->nr_frags; ++i) {
++              const skb_frag_t *f = &shi->frags[i];
++              unsigned int offset = skb_frag_off(f);
++              struct page *page;
++
++              page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
++              sg_set_page(&sg, page, skb_frag_size(f), offset_in_page(offset));
++              ahash_request_set_crypt(req, &sg, NULL, skb_frag_size(f));
++              if (crypto_ahash_update(req))
++                      return 1;
++      }
++
++      skb_walk_frags(skb, frag_iter)
++              if (tcp_sigpool_hash_skb_data(hp, frag_iter, 0))
++                      return 1;
++
++      return 0;
++}
++EXPORT_SYMBOL(tcp_sigpool_hash_skb_data);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Per-CPU pool of crypto requests");
+diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
+index 2c579868fe81f..689c0b383ebf9 100644
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -665,7 +665,7 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
+                             cmd.tcpm_key, cmd.tcpm_keylen);
+ }
+-static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
++static int tcp_v6_md5_hash_headers(struct tcp_sigpool *hp,
+                                  const struct in6_addr *daddr,
+                                  const struct in6_addr *saddr,
+                                  const struct tcphdr *th, int nbytes)
+@@ -686,39 +686,36 @@ static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
+       _th->check = 0;
+       sg_init_one(&sg, bp, sizeof(*bp) + sizeof(*th));
+-      ahash_request_set_crypt(hp->md5_req, &sg, NULL,
++      ahash_request_set_crypt(hp->req, &sg, NULL,
+                               sizeof(*bp) + sizeof(*th));
+-      return crypto_ahash_update(hp->md5_req);
++      return crypto_ahash_update(hp->req);
+ }
+ static int tcp_v6_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
+                              const struct in6_addr *daddr, struct in6_addr *saddr,
+                              const struct tcphdr *th)
+ {
+-      struct tcp_md5sig_pool *hp;
+-      struct ahash_request *req;
++      struct tcp_sigpool hp;
+-      hp = tcp_get_md5sig_pool();
+-      if (!hp)
+-              goto clear_hash_noput;
+-      req = hp->md5_req;
++      if (tcp_sigpool_start(tcp_md5_sigpool_id, &hp))
++              goto clear_hash_nostart;
+-      if (crypto_ahash_init(req))
++      if (crypto_ahash_init(hp.req))
+               goto clear_hash;
+-      if (tcp_v6_md5_hash_headers(hp, daddr, saddr, th, th->doff << 2))
++      if (tcp_v6_md5_hash_headers(&hp, daddr, saddr, th, th->doff << 2))
+               goto clear_hash;
+-      if (tcp_md5_hash_key(hp, key))
++      if (tcp_md5_hash_key(&hp, key))
+               goto clear_hash;
+-      ahash_request_set_crypt(req, NULL, md5_hash, 0);
+-      if (crypto_ahash_final(req))
++      ahash_request_set_crypt(hp.req, NULL, md5_hash, 0);
++      if (crypto_ahash_final(hp.req))
+               goto clear_hash;
+-      tcp_put_md5sig_pool();
++      tcp_sigpool_end(&hp);
+       return 0;
+ clear_hash:
+-      tcp_put_md5sig_pool();
+-clear_hash_noput:
++      tcp_sigpool_end(&hp);
++clear_hash_nostart:
+       memset(md5_hash, 0, 16);
+       return 1;
+ }
+@@ -728,10 +725,9 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
+                              const struct sock *sk,
+                              const struct sk_buff *skb)
+ {
+-      const struct in6_addr *saddr, *daddr;
+-      struct tcp_md5sig_pool *hp;
+-      struct ahash_request *req;
+       const struct tcphdr *th = tcp_hdr(skb);
++      const struct in6_addr *saddr, *daddr;
++      struct tcp_sigpool hp;
+       if (sk) { /* valid for establish/request sockets */
+               saddr = &sk->sk_v6_rcv_saddr;
+@@ -742,30 +738,28 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
+               daddr = &ip6h->daddr;
+       }
+-      hp = tcp_get_md5sig_pool();
+-      if (!hp)
+-              goto clear_hash_noput;
+-      req = hp->md5_req;
++      if (tcp_sigpool_start(tcp_md5_sigpool_id, &hp))
++              goto clear_hash_nostart;
+-      if (crypto_ahash_init(req))
++      if (crypto_ahash_init(hp.req))
+               goto clear_hash;
+-      if (tcp_v6_md5_hash_headers(hp, daddr, saddr, th, skb->len))
++      if (tcp_v6_md5_hash_headers(&hp, daddr, saddr, th, skb->len))
+               goto clear_hash;
+-      if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
++      if (tcp_sigpool_hash_skb_data(&hp, skb, th->doff << 2))
+               goto clear_hash;
+-      if (tcp_md5_hash_key(hp, key))
++      if (tcp_md5_hash_key(&hp, key))
+               goto clear_hash;
+-      ahash_request_set_crypt(req, NULL, md5_hash, 0);
+-      if (crypto_ahash_final(req))
++      ahash_request_set_crypt(hp.req, NULL, md5_hash, 0);
++      if (crypto_ahash_final(hp.req))
+               goto clear_hash;
+-      tcp_put_md5sig_pool();
++      tcp_sigpool_end(&hp);
+       return 0;
+ clear_hash:
+-      tcp_put_md5sig_pool();
+-clear_hash_noput:
++      tcp_sigpool_end(&hp);
++clear_hash_nostart:
+       memset(md5_hash, 0, 16);
+       return 1;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch b/queue-6.6/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
new file mode 100644 (file)
index 0000000..c0879fd
--- /dev/null
@@ -0,0 +1,117 @@
+From e4a98c4d2af4456541dca21224fa7c707150ae56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:38:50 +0000
+Subject: net: thunderbolt: Tear down DMA paths before stopping the rings
+
+From: Fan XinRan <shinjiangjiang@gmail.com>
+
+[ Upstream commit 68bf02b6b4ad3f748c6db71fd77b6c0402d252f4 ]
+
+tbnet_tear_down() stops both rings and frees their frame buffers before
+calling tb_xdomain_disable_paths().  tb_ring_stop() zeroes the ring's
+descriptor base and tbnet_free_buffers() unmaps and frees the pages the
+frames sit in, so by the time __tb_path_deactivate_hop() polls the hop's
+'pending' bit, anything still in flight has nowhere to drain to.
+
+The teardown sequence has been in this order since the driver was added.
+The setup path has not: commit ff7cd07f3064 ("net: thunderbolt: Enable
+DMA paths only after rings are enabled") moved the path enable to the end
+of tbnet_connected_work() and documented why:
+
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
+        */
+
+Teardown was never updated to match, so the rings and the paths now come
+down in the same order they go up instead of in reverse.
+
+On an ASMedia ASM4242 host router the 'pending' bit then never clears:
+every teardown burns the full 500 ms timeout and
+__tb_path_deactivate_hop() returns -ETIMEDOUT.  Raising the timeout to
+5 s does not help, so the hop is not slow to drain, it never drains
+at all.
+
+The failure is invisible above the thunderbolt core.
+__tb_path_deactivate_hops() is void and only calls tb_port_warn();
+tb_path_deactivate(), tb_tunnel_deactivate() and
+__tb_disconnect_xdomain_paths() are void as well, and
+tb_disconnect_xdomain_paths() ends in an unconditional "return 0".  So
+tb_xdomain_disable_paths() reports success and the netdev_warn() below
+it never fires.  Repeated teardowns eventually take the XDomain control
+channel down, after which the peer node is gone and only a power cycle
+brings the controller back.
+
+Deactivating the paths first fixes it.  Measured with kretprobes on a
+stock v6.17 tree with no other patches applied, on a link that was up
+and had just carried traffic:
+
+  before: __tb_path_deactivate_hop() returns 0 for the first hop, then
+          -ETIMEDOUT for the second 500335 us later
+  after:  0 for both, 525 us apart
+
+Alternating the two orderings ABBA over three load levels, four
+teardowns per arm: every teardown failed before the change (21 of 21
+that ran), none failed after (0 of 24).  The before arms ran short
+because the link died partway through.  The same split shows up when
+the interface is enslaved to a bond instead of just brought down, which
+is how I ran into this in the first place.  Throughput and latency after
+the change are unchanged.
+
+Hosts whose routers drain the hop despite the stale descriptor base see
+no functional difference, since the paths end up deactivated either way.
+
+Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
+Signed-off-by: Fan XinRan <shinjiangjiang@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260803-b4-tbnet-teardown-v2-1-27de6a13ca2d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 960839a651e51..ceaba08cd378a 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -389,11 +389,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+                               break;
+               }
+-              tb_ring_stop(net->rx_ring.ring);
+-              tb_ring_stop(net->tx_ring.ring);
+-              tbnet_free_buffers(&net->rx_ring);
+-              tbnet_free_buffers(&net->tx_ring);
+-
++              /* Tear the paths down before stopping the rings.  This mirrors
++               * tbnet_connected_work(), which enables the paths last so the
++               * Rx ring is primed before packets can arrive.  Stopping a
++               * ring zeroes its descriptor base and tbnet_free_buffers()
++               * unmaps and frees the frame buffers, leaving anything still
++               * in flight with nowhere to drain to;
++               * __tb_path_deactivate_hop() then waits for the hop's
++               * 'pending' bit, which on some host routers never clears in
++               * that state.
++               */
+               ret = tb_xdomain_disable_paths(net->xd,
+                                              net->local_transmit_path,
+                                              net->tx_ring.ring->hop,
+@@ -402,6 +407,11 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+               if (ret)
+                       netdev_warn(net->dev, "failed to disable DMA paths\n");
++              tb_ring_stop(net->rx_ring.ring);
++              tb_ring_stop(net->tx_ring.ring);
++              tbnet_free_buffers(&net->rx_ring);
++              tbnet_free_buffers(&net->tx_ring);
++
+               tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+               net->remote_transmit_path = 0;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.6/netfilter-ipset-switch-ext_size-to-atomic64_t.patch b/queue-6.6/netfilter-ipset-switch-ext_size-to-atomic64_t.patch
new file mode 100644 (file)
index 0000000..661d14c
--- /dev/null
@@ -0,0 +1,134 @@
+From 1e43c1acf9529cd4e04e08a0e3abdbe5eff64256 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 20:38:50 +0200
+Subject: netfilter: ipset: switch ext_size to atomic64_t
+
+From: Jozsef Kadlecsik <kadlec@netfilter.org>
+
+[ Upstream commit 712a6f545c359b427daa9a5a782e30d2f8331e25 ]
+
+The hash types do not acquire set->lock, they use 'region locking' where
+only part of the hash table is locked. Parallel inserts and deletes are
+possible and CPUs can race on ->ext_size update.  Switch to atomic64_t.
+
+This leaves another bug unresolved: there still can be a race on
+comment extension re-init.  This will be handled in a later commit
+when converting to rhashtable backend.
+
+Fixes: f66ee0410b1c ("netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports")
+Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netfilter/ipset/ip_set.h  | 2 +-
+ net/netfilter/ipset/ip_set_bitmap_gen.h | 4 ++--
+ net/netfilter/ipset/ip_set_core.c       | 6 +++---
+ net/netfilter/ipset/ip_set_hash_gen.h   | 2 +-
+ net/netfilter/ipset/ip_set_list_set.c   | 4 ++--
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
+index b98331572ad29..cadae9b2578f1 100644
+--- a/include/linux/netfilter/ipset/ip_set.h
++++ b/include/linux/netfilter/ipset/ip_set.h
+@@ -273,7 +273,7 @@ struct ip_set {
+       /* Number of elements (vs timeout) */
+       u32 elements;
+       /* Size of the dynamic extensions (vs timeout) */
+-      size_t ext_size;
++      atomic64_t ext_size;
+       /* Element data size */
+       size_t dsize;
+       /* Offsets to extensions in elements */
+diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
+index 9523104a90da4..40f0383883f9d 100644
+--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
++++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
+@@ -75,7 +75,7 @@ mtype_flush(struct ip_set *set)
+               mtype_ext_cleanup(set);
+       bitmap_zero(map->members, map->elements);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ /* Calculate the actual memory size of the set data */
+@@ -91,7 +91,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct mtype *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = mtype_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index f51a1af31513c..29bf5ee74fe36 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -350,7 +350,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       size_t len = ext->comment ? strlen(ext->comment) : 0;
+       if (unlikely(c)) {
+-              set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++              atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+               rcu_assign_pointer(comment->c, NULL);
+               kfree_rcu(c, rcu);
+       }
+@@ -362,7 +362,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       if (unlikely(!c))
+               return;
+       strscpy(c->str, ext->comment, len + 1);
+-      set->ext_size += sizeof(*c) + strlen(c->str) + 1;
++      atomic64_add(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, c);
+ }
+ EXPORT_SYMBOL_GPL(ip_set_init_comment);
+@@ -392,7 +392,7 @@ ip_set_comment_free(struct ip_set *set, void *ptr)
+       c = rcu_dereference_protected(comment->c, 1);
+       if (unlikely(!c))
+               return;
+-      set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++      atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, NULL);
+       kfree_rcu(c, rcu);
+ }
+diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
+index 81ad6747bc7a4..53b65f013594a 100644
+--- a/net/netfilter/ipset/ip_set_hash_gen.h
++++ b/net/netfilter/ipset/ip_set_hash_gen.h
+@@ -1288,7 +1288,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+-      memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
++      memsize = mtype_ahash_memsize(h, t) + ext_size + atomic64_read(&set->ext_size);
+       htable_bits = t->htable_bits;
+       rcu_read_unlock_bh();
+diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
+index 83e1fdcc752d6..9d6ab69ca1a37 100644
+--- a/net/netfilter/ipset/ip_set_list_set.c
++++ b/net/netfilter/ipset/ip_set_list_set.c
+@@ -421,7 +421,7 @@ list_set_flush(struct ip_set *set)
+       list_for_each_entry_safe(e, n, &map->members, list)
+               list_set_del(set, e);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ static void
+@@ -455,7 +455,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct list_set *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = list_set_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = list_set_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+-- 
+2.53.0
+
diff --git a/queue-6.6/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-6.6/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..327f98b
--- /dev/null
@@ -0,0 +1,50 @@
+From ed1bf91cdc5ba8071ddc04646dfc9256cc9ac3a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 42fa7c915e29b..ce3ab0a9c0ef7 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10383,6 +10383,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10424,6 +10425,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-6.6/regulator-devres-add-api-for-reference-voltage-suppl.patch b/queue-6.6/regulator-devres-add-api-for-reference-voltage-suppl.patch
new file mode 100644 (file)
index 0000000..4017b5f
--- /dev/null
@@ -0,0 +1,135 @@
+From a425b1ed1110b9a585f510df8c6f7e64b67c0b86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 18:40:09 -0500
+Subject: regulator: devres: add API for reference voltage supplies
+
+From: David Lechner <dlechner@baylibre.com>
+
+[ Upstream commit b250c20b64290808aa4b5cc6d68819a7ee28237f ]
+
+A common use case for regulators is to supply a reference voltage to an
+analog input or output device. This adds a new devres API to get,
+enable, and get the voltage in a single call. This allows eliminating
+boilerplate code in drivers that use reference supplies in this way.
+
+Signed-off-by: David Lechner <dlechner@baylibre.com>
+Link: https://lore.kernel.org/r/20240429-regulator-get-enable-get-votlage-v2-1-b1f11ab766c1@baylibre.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: fddb5ceaf901 ("hwmon: (ads7828) Fix external VREF regulator handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../driver-api/driver-model/devres.rst        |  1 +
+ drivers/regulator/devres.c                    | 59 +++++++++++++++++++
+ include/linux/regulator/consumer.h            |  7 +++
+ 3 files changed, 67 insertions(+)
+
+diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
+index 8be086b3f8297..3fe1711dd587c 100644
+--- a/Documentation/driver-api/driver-model/devres.rst
++++ b/Documentation/driver-api/driver-model/devres.rst
+@@ -426,6 +426,7 @@ REGULATOR
+   devm_regulator_bulk_put()
+   devm_regulator_get()
+   devm_regulator_get_enable()
++  devm_regulator_get_enable_read_voltage()
+   devm_regulator_get_enable_optional()
+   devm_regulator_get_exclusive()
+   devm_regulator_get_optional()
+diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
+index 90bb0d178885a..4f290b9b559b9 100644
+--- a/drivers/regulator/devres.c
++++ b/drivers/regulator/devres.c
+@@ -145,6 +145,65 @@ struct regulator *devm_regulator_get_optional(struct device *dev,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
++/**
++ * devm_regulator_get_enable_read_voltage - Resource managed regulator get and
++ *                                          enable that returns the voltage
++ * @dev: device to supply
++ * @id:  supply name or regulator ID.
++ *
++ * Get and enable regulator for duration of the device life-time.
++ * regulator_disable() and regulator_put() are automatically called on driver
++ * detach. See regulator_get_optional(), regulator_enable(), and
++ * regulator_get_voltage() for more information.
++ *
++ * This is a convenience function for supplies that provide a reference voltage
++ * where the consumer driver just needs to know the voltage and keep the
++ * regulator enabled.
++ *
++ * In cases where the supply is not strictly required, callers can check for
++ * -ENODEV error and handle it accordingly.
++ *
++ * Returns: voltage in microvolts on success, or an error code on failure.
++ */
++int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id)
++{
++      struct regulator *r;
++      int ret;
++
++      /*
++       * Since we need a real voltage, we use devm_regulator_get_optional()
++       * rather than getting a dummy regulator with devm_regulator_get() and
++       * then letting regulator_get_voltage() fail with -EINVAL. This way, the
++       * caller can handle the -ENODEV error code if needed instead of the
++       * ambiguous -EINVAL.
++       */
++      r = devm_regulator_get_optional(dev, id);
++      if (IS_ERR(r))
++              return PTR_ERR(r);
++
++      ret = regulator_enable(r);
++      if (ret)
++              goto err_regulator_put;
++
++      ret = devm_add_action_or_reset(dev, regulator_action_disable, r);
++      if (ret)
++              goto err_regulator_put;
++
++      ret = regulator_get_voltage(r);
++      if (ret < 0)
++              goto err_release_action;
++
++      return 0;
++
++err_release_action:
++      devm_release_action(dev, regulator_action_disable, r);
++err_regulator_put:
++      devm_regulator_put(r);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(devm_regulator_get_enable_read_voltage);
++
+ static int devm_regulator_match(struct device *dev, void *res, void *data)
+ {
+       struct regulator **r = res;
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index 25d0684d37b3e..9a2f1e9a94a85 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -209,6 +209,7 @@ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
+                                                          const char *id);
+ int devm_regulator_get_enable(struct device *dev, const char *id);
+ int devm_regulator_get_enable_optional(struct device *dev, const char *id);
++int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id);
+ void regulator_put(struct regulator *regulator);
+ void devm_regulator_put(struct regulator *regulator);
+@@ -374,6 +375,12 @@ static inline int devm_regulator_get_enable_optional(struct device *dev,
+       return 0;
+ }
++static inline int devm_regulator_get_enable_read_voltage(struct device *dev,
++                                                       const char *id)
++{
++      return -ENODEV;
++}
++
+ static inline struct regulator *__must_check
+ regulator_get_optional(struct device *dev, const char *id)
+ {
+-- 
+2.53.0
+
diff --git a/queue-6.6/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch b/queue-6.6/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
new file mode 100644 (file)
index 0000000..6122c75
--- /dev/null
@@ -0,0 +1,104 @@
+From bcaadac1036df10f32dd5435beeeb6b500d14337 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 12:29:48 +0000
+Subject: Revert "net: thunderbolt: Enable end-to-end flow control also in
+ transmit"
+
+From: Fan Ye <fy15309206903@gmail.com>
+
+[ Upstream commit 1881f2efbf7f78dc0a79a387b29fde6ff56d3731 ]
+
+This reverts commit a8065af3346ebd7c76ebc113451fb3ba94cf7769.
+
+Per the USB4 spec, a Transmit Descriptor Ring with E2E flow control
+disabled does not require any credits to be available before the Host
+Interface Adapter Layer transmits a tunneled packet from it. Once E2E is
+enabled on that ring the controller must first obtain end-to-end
+credits.
+
+The ASMedia ASM4242 USB4 host router (PCI 1b21:2425) never delivers
+those credits. The controller does accept the configuration: reading the
+ring OPTIONS register back right after tb_ring_start() returns exactly
+what was written, including RING_FLAG_E2E_FLOW_CONTROL (bit 28) and the
+E2E HopID field. No credit ever arrives though, so the Tx ring's
+hardware consumer index never advances and the link carries no traffic
+at all.
+
+Measured on two hosts connected point to point, onboard ASM4242 on MSI
+X870E and X870, v6.17, stock drivers/net/thunderbolt/main.c with only
+this revert applied on top:
+
+  before: 100% packet loss to the peer; thunderbolt0 is up and the
+          XDomain handshake completes ("new host found"), but iperf3
+          fails with "No route to host" once the neighbour entry
+          expires
+  after:  0% packet loss, 0.28 ms RTT; iperf3 4.21 Gb/s one way and
+          5.17 Gb/s the other (5 runs each, stddev <= 0.02), 1
+          retransmit in 10 s
+
+An instrumented build additionally showed a frozen-Tx-consumer watchdog
+firing ~30k times in a 10 s window before this change.
+
+Rx-side E2E is not touched by this revert, so peers that do return
+credits keep receive-side flow control.
+
+ASMedia does not look like an isolated case. The out-of-tree
+thunderbolt-ibverbs project disables native E2E on AMD NHI by default,
+noting that "Strix Halo has reproduced TX completion wedges with
+multiple native E2E rings active" -- the same failure mode, on a
+different vendor. Since the driver has no way to tell in advance which
+host router returns the credits, going back to the previous behaviour
+looks safer than adding a quirk per affected part; Tx-side E2E can be
+reintroduced as an opt-in for controllers that are known to implement
+the credit return.
+
+Note that the reverted commit was not fixing a reported problem, it was
+derived from the spec wording alone, so this revert is not expected to
+regress a known workload. Cc'ing the original author in case there was
+one.
+
+Fixes: a8065af3346e ("net: thunderbolt: Enable end-to-end flow control also in transmit")
+Cc: zhangjianrong <zhangjianrong5@huawei.com>
+Signed-off-by: Fan Ye <fy15309206903@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260727123002.25225-1-fy15309206903@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 5d7d11d75b0b8..960839a651e51 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -928,12 +928,8 @@ static int tbnet_open(struct net_device *dev)
+       netif_carrier_off(dev);
+-      flags = RING_FLAG_FRAME;
+-      /* Only enable full E2E if the other end supports it too */
+-      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
+-              flags |= RING_FLAG_E2E;
+-
+-      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags);
++      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE,
++                              RING_FLAG_FRAME);
+       if (!ring) {
+               netdev_err(dev, "failed to allocate Tx ring\n");
+               return -ENOMEM;
+@@ -952,6 +948,11 @@ static int tbnet_open(struct net_device *dev)
+       sof_mask = BIT(TBIP_PDF_FRAME_START);
+       eof_mask = BIT(TBIP_PDF_FRAME_END);
++      flags = RING_FLAG_FRAME;
++      /* Only enable full E2E if the other end supports it too */
++      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
++              flags |= RING_FLAG_E2E;
++
+       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags,
+                               net->tx_ring.ring->hop, sof_mask,
+                               eof_mask, tbnet_start_poll, net);
+-- 
+2.53.0
+
diff --git a/queue-6.6/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-6.6/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..6554cd5
--- /dev/null
@@ -0,0 +1,54 @@
+From e4f48aeb9e232fbcc71ca314c1af41b44513274a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 44f06c5f1f256..ebdc48be47813 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -573,6 +573,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-6.6/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-6.6/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..16ee334
--- /dev/null
@@ -0,0 +1,57 @@
+From f7034fc517df12f7c7ae1c022389fce66fe6a512 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 0f03560fcab44..1a614560223ef 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3354,12 +3354,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-6.6/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch b/queue-6.6/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
new file mode 100644 (file)
index 0000000..bdd6117
--- /dev/null
@@ -0,0 +1,88 @@
+From 5e14cad88e4ae3e56d88f7a9edde992bafd950c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 21:46:35 +0200
+Subject: selftests/ftrace: refactor eprobes test to fix argument checks
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+[ Upstream commit 6e3abef2a27e7402a94111c9eff85d887e64a309 ]
+
+The add/remove eprobe test installs an eprobe for the openat syscall and
+runs ls. It checks the filenames that were opened by ls against a
+whitelist and a blacklist.
+
+Commit 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING
+pointer") fixed access to some string fields in eprobes. This triggers
+test failures as the blacklist does not allow relative paths for the
+openat parameters.
+
+What makes this test unstable is the fact that the openat calls vary a
+lot between different systems.
+
+Refactor the test to make it more robust. "cd <directory>" will issue a
+chdir syscall with the target directory as parameter. Set an eprobe on
+the sys_enter_chdir event and filter for the exact directory name. Allow
+(fault) as fallback.
+
+Link: https://lore.kernel.org/all/20260804194705.760893-1-martin@kaiser.cx/
+
+Fixes: 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING pointer")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202607151010.b68428e1-lkp@intel.com
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc  | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index c300eb0202620..e2322693d0c32 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,16 +1,16 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+ clear_dynamic_events
+ SYSTEM="syscalls"
+-EVENT="sys_enter_openat"
++EVENT="sys_enter_chdir"
+ FIELD="filename"
+-EPROBE="eprobe_open"
++EPROBE="eprobe_chdir"
+ OPTIONS="file=+0(\$filename):ustring"
+ echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+@@ -18,20 +18,14 @@ grep -q "$EPROBE" dynamic_events
+ test -d events/eprobes/$EPROBE
+ echo 1 > events/eprobes/$EPROBE/enable
+-ls
++cd /sys/kernel/tracing
+ echo 0 > events/eprobes/$EPROBE/enable
+-content=`grep '^ *ls-' trace | grep 'file='`
+-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
+-
++content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
+ if [ -z "$content" ]; then
+       exit_fail
+ fi
+-if [ ! -z "$nocontent" ]; then
+-      exit_fail
+-fi
+-
+ echo "-:$EPROBE" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+-- 
+2.53.0
+
index aa60066a86c9c273b8c19483e8958d0611e6f1d3..cd27521ef5365ea91bf5cd91978d3fb4f68a3e7f 100644 (file)
@@ -1,3 +1,62 @@
 mount-honour-sb_nouser-in-the-new-mount-api.patch
 selftests-bpf-fail-unbound-udp-on-sockmap-update.patch
 s390-zcrypt-fix-missing-mem-scrub-at-clear-key-impor.patch
+arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
+drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
+revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
+netfilter-ipset-switch-ext_size-to-atomic64_t.patch
+ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
+ipvs-return-the-csum-validation-for-forward-hook.patch
+btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+devlink-fix-net-namespace-reference-leak-in-reload.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+bpf-tcp-make-mem-flags-configurable-through-bpf_iter.patch
+bpf-tcp-make-sure-iter-batch-always-contains-a-full-.patch
+bpf-tcp-get-rid-of-st_bucket_done.patch
+bpf-tcp-use-bpf_tcp_iter_batch_item-for-bpf_tcp_iter.patch
+bpf-tcp-avoid-socket-skips-and-repeats-during-iterat.patch
+bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
+vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
+tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+net-sched-cls_api-add-skip_sw-counter.patch
+net-sched-cls_api-add-filter-counter.patch
+net-sched-make-skip_sw-actually-skip-software.patch
+net-sched-cls_api-fix-slab-use-after-free-in-fl_dump.patch
+net-sched-refine-software-bypass-handling-in-tc_run.patch
+net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
+hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
+hwmon-lm25066-use-i2c_get_match_data.patch
+hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
+selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
+bnxt_en-do-not-set-eop-on-rx-agg-bds-on-5760x-chips.patch
+bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
+bnxt_en-fix-ptp-pps-setting-bug.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
+net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+net-tcp-prepare-tcp_md5sig_pool-for-tcp-ao.patch
+net-tcp-add-tcp-ao-config-and-structures.patch
+net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
+hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
+regulator-devres-add-api-for-reference-voltage-suppl.patch
+hwmon-ads7828-fix-external-vref-regulator-handling.patch
diff --git a/queue-6.6/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch b/queue-6.6/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
new file mode 100644 (file)
index 0000000..8f91014
--- /dev/null
@@ -0,0 +1,61 @@
+From 09ccb6451412337ba0de04ec60d7d161814e0e66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 20:08:06 -0700
+Subject: tcp: do not change rcv_ssthresh in tcp_measure_rcv_mss()
+
+From: Nathan Gao <zcgao@amazon.com>
+
+[ Upstream commit 0e125ecfe20c077625cf0be8d750d5c3abc0dce9 ]
+
+Commit f5da7c45188e ("tcp: adjust rcvq_space after updating scaling
+ratio") replaced the direct window_clamp update in tcp_measure_rcv_mss()
+with a call to tcp_set_window_clamp(), a helper that implements the
+TCP_WINDOW_CLAMP setsockopt. As a side effect, the helper also shrinks
+rcv_ssthresh via __tcp_adjust_rcv_ssthresh().
+
+As a result, each scaling_ratio decrease detected by
+tcp_measure_rcv_mss() also cuts rcv_ssthresh. Elsewhere in TCP,
+rcv_ssthresh is usually cut under memory pressure and grows via
+tcp_grow_window().
+
+Flows whose segment sizes vary keep scaling_ratio oscillating, which
+leads to an unstable rcv_ssthresh: a dip of rcv_ssthresh only recovers
+via tcp_grow_window(), keeping the advertised window at a relatively
+low level even after the ratio itself has recovered, and can even stall
+the sender.
+
+Observed on a customer's proxy gateway after upgrading from kernel 6.1
+to 6.12: in the worst case, rcv_ssthresh was cut in half by a
+scaling_ratio dip. P99 latency jumped from <10ms on 6.1 to ~100ms on
+6.12, and almost returned to the 6.1 level with this patch applied.
+
+Restore the plain WRITE_ONCE() update of window_clamp, as introduced
+in commit a2cbb1603943 ("tcp: Update window clamping condition"), and
+keep the rcvq_space.space adjustment. Now rcv_ssthresh is decoupled from
+scaling_ratio changes in tcp_measure_rcv_mss().
+
+Fixes: f5da7c45188e ("tcp: adjust rcvq_space after updating scaling ratio")
+Signed-off-by: Nathan Gao <zcgao@amazon.com>
+Link: https://patch.msgid.link/20260725030806.28135-1-zcgao@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index eb1bf58634741..9efb84658a82d 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -252,7 +252,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
+                               struct tcp_sock *tp = tcp_sk(sk);
+                               val = tcp_win_from_space(sk, sk->sk_rcvbuf);
+-                              tcp_set_window_clamp(sk, val);
++                              WRITE_ONCE(tp->window_clamp, val);
+                               if (tp->window_clamp < tp->rcvq_space.space)
+                                       tp->rcvq_space.space = tp->window_clamp;
+-- 
+2.53.0
+
diff --git a/queue-6.6/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch b/queue-6.6/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
new file mode 100644 (file)
index 0000000..c45dc1d
--- /dev/null
@@ -0,0 +1,72 @@
+From a46dc029eed5866bd2c1669fe423ce66a0f9f9a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:17:38 +0800
+Subject: tcp: fix TFO max_qlen accounting across reuseport migration
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit a0ab2ba83e35159d81cec830a92e885ecf8139be ]
+
+A listener's TCP_FASTOPEN max_qlen stops being accurate and lets through
+far more pending Fast Open requests than it was configured for.
+
+This only shows up with SO_REUSEPORT listener migration, where closing a
+listener hands its still-pending TFO children over to a surviving one.
+
+fastopenq.qlen is charged in tcp_fastopen_create_child() when the child
+is created and uncharged in reqsk_fastopen_remove() when the handshake
+completes.  The uncharge follows rsk_listener of the request the child
+points at, and inet_reqsk_clone() has repointed the child at a new
+request owned by the new listener, so the ++ and the -- land on two
+different sockets.  The new listener's qlen drifts negative and its
+limit no longer binds.
+
+Charge the new listener during migration, like reqsk_queue_migrated()
+already does for queue->young and queue->qlen.
+
+Fixes: 54b92e841937 ("tcp: Migrate TCP_ESTABLISHED/TCP_SYN_RECV sockets in accept queues.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260803061739.134737-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index c7a1f763e464e..208f8b173a056 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -930,11 +930,23 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
+       nreq->rsk_listener = sk;
+-      /* We need not acquire fastopenq->lock
+-       * because the child socket is locked in inet_csk_listen_stop().
+-       */
+-      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
++      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener) {
++              struct fastopen_queue *fastopenq;
++
++              /* reqsk_fastopen_remove() will uncharge nreq->rsk_listener,
++               * that is @sk, so charge it here.  Unlike the listener
++               * being closed, @sk is live and needs its lock.
++               */
++              fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
++              spin_lock_bh(&fastopenq->lock);
++              fastopenq->qlen++;
++              spin_unlock_bh(&fastopenq->lock);
++
++              /* We need not acquire fastopenq->lock
++               * because the child socket is locked in inet_csk_listen_stop().
++               */
+               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
++      }
+       return nreq;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-6.6/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..4a53041
--- /dev/null
@@ -0,0 +1,45 @@
+From c5720e98f7248ca4fb676480759005646192cab9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 39021fab3c596..719cc70b26505 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -458,7 +458,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-6.6/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-6.6/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..1b517eb
--- /dev/null
@@ -0,0 +1,53 @@
+From 4de2cb64ae2f6d0e9c78683919829dc9c96d0e79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 84ae2759ff195..b9b21e5af1a7f 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -22,17 +22,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-6.6/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch b/queue-6.6/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
new file mode 100644 (file)
index 0000000..0cd0ff5
--- /dev/null
@@ -0,0 +1,56 @@
+From 9dbd818c63fb2834e3ad06811735b6e8e388cb79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:02:02 -0700
+Subject: vhost/vdpa: reject overflowing PA map page counts on 32-bit
+
+From: Yousef Alhouseen <alhouseenyousef@gmail.com>
+
+[ Upstream commit 0619aaa34c0c2a2dcb07f0e9c8a34e7efb8c4cdf ]
+
+vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
+size before computing the number of pages to pin. On 32-bit systems,
+where unsigned long is narrower than u64, that addition can overflow and
+the code can pin and map fewer pages than the requested IOTLB range.
+
+Reject sizes that overflow the unsigned long page-count calculation.
+
+Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and vhost_vdpa_pa_unmap()")
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index 3645d83f240d9..5e2f7f4477679 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -998,6 +998,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       unsigned int gup_flags = FOLL_LONGTERM;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
++      unsigned long page_offset;
+       u64 start = iova;
+       long pinned;
+       int ret = 0;
+@@ -1010,7 +1011,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       if (perm & VHOST_ACCESS_WO)
+               gup_flags |= FOLL_WRITE;
+-      npages = PFN_UP(size + (iova & ~PAGE_MASK));
++      page_offset = iova & ~PAGE_MASK;
++      if (size > ULONG_MAX - page_offset) {
++              ret = -EINVAL;
++              goto free;
++      }
++
++      npages = PFN_UP(size + page_offset);
+       if (!npages) {
+               ret = -EINVAL;
+               goto free;
+-- 
+2.53.0
+
diff --git a/queue-7.1/accel-amdxdna-fix-locally-exploitable-bug_on-in-amdx.patch b/queue-7.1/accel-amdxdna-fix-locally-exploitable-bug_on-in-amdx.patch
new file mode 100644 (file)
index 0000000..7922c5e
--- /dev/null
@@ -0,0 +1,86 @@
+From a90890f9986886308a5036e1bef64b29306dc3a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 11:59:55 -0700
+Subject: accel/amdxdna: Fix locally exploitable BUG_ON in
+ amdxdna_insert_pages()
+
+From: Lizhi Hou <lizhi.hou@amd.com>
+
+[ Upstream commit 4a19f7ab5972ef608b31ae921419bc3e04b3f8ad ]
+
+In amdxdna_insert_pages(), vm_flags_mod() sets VM_MIXEDMAP and clears
+VM_PFNMAP. If an unprivileged userspace process mmaps a non-imported GEM
+object and then calls madvise(MADV_DONTNEED), the PTEs will be
+successfully cleared because VM_MIXEDMAP allows this (unlike VM_PFNMAP).
+
+When userspace subsequently accesses the memory, drm_gem_shmem_fault()
+handles the page fault and attempts to map the backing shmem page via
+vmf_insert_pfn() which calls vmf_insert_pfn_prot(). Because the backing
+shmem page is normal system memory (pfn_valid(pfn) is true) and the VMA
+now has VM_MIXEDMAP set, won't this predictably trigger the explicit
+assertion BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn))
+
+Fix by removing the vm_flags_mod() call and replacing the vm_insert_pages()
+pre-population with the handle_mm_fault() loop that was already used for
+the import (dma-buf) path.
+
+Fixes: e486147c912f ("accel/amdxdna: Add BO import and export")
+Reviewed-by: Max Zhen <max.zhen@amd.com>
+Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
+Link: https://patch.msgid.link/20260731185955.3449311-1-lizhi.hou@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/amdxdna/amdxdna_gem.c | 27 ++++++++-------------------
+ 1 file changed, 8 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
+index 41fb39d095749..fff1c707d040a 100644
+--- a/drivers/accel/amdxdna/amdxdna_gem.c
++++ b/drivers/accel/amdxdna/amdxdna_gem.c
+@@ -402,25 +402,17 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
+                       XDNA_ERR(xdna, "Failed shmem mmap %d", ret);
+                       return ret;
+               }
+-
+-              /* The buffer is based on memory pages. Fix the flag. */
+-              vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
+-              ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages,
+-                                    &num_pages);
++      } else {
++              vma->vm_private_data = NULL;
++              vma->vm_ops = NULL;
++              ret = dma_buf_mmap(abo->dma_buf, vma, 0);
+               if (ret) {
+-                      XDNA_ERR(xdna, "Failed insert pages %d", ret);
+-                      amdxdna_mark_mapp_invalid(abo, vma);
++                      XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
++                      return ret;
+               }
+-              return 0;
+-      }
+-
+-      vma->vm_private_data = NULL;
+-      vma->vm_ops = NULL;
+-      ret = dma_buf_mmap(abo->dma_buf, vma, 0);
+-      if (ret) {
+-              XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
+-              return ret;
++              /* Drop the reference drm_gem_mmap_obj() acquired.*/
++              drm_gem_object_put(to_gobj(abo));
+       }
+       do {
+@@ -437,9 +429,6 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
+               offset += PAGE_SIZE;
+       } while (--num_pages);
+-      /* Drop the reference drm_gem_mmap_obj() acquired.*/
+-      drm_gem_object_put(to_gobj(abo));
+-
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/accel-amxdna-fix-page-insertion-errors-in-amdxdna_in.patch b/queue-7.1/accel-amxdna-fix-page-insertion-errors-in-amdxdna_in.patch
new file mode 100644 (file)
index 0000000..55da1bb
--- /dev/null
@@ -0,0 +1,88 @@
+From 06d3584193b29dd8e735c47bea538cc00b1b235b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 00:42:56 -0700
+Subject: accel/amxdna: Fix page-insertion errors in amdxdna_insert_pages()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lizhi Hou <lizhi.hou@amd.com>
+
+[ Upstream commit 8d51e0fd3e698919d2adeff71936377f0c0d4aa0 ]
+
+Two error paths in amdxdna_insert_pages() called vma->vm_ops->close(vma)
+before returning an error code to the caller.  This is incorrect:
+amdxdna_gem_obj_mmap() registers an HMM interval notifier before calling
+amdxdna_insert_pages(), and on a hard error it jumps to hmm_unreg to undo
+that registration.  Calling vm_ops->close() manually — which drops the
+shmem pages_pin_count and the GEM object reference that backs the VMA —
+before the mmap syscall has even returned causes those resources to be
+released while the VMA is still alive.  The kernel VMA teardown will call
+vm_ops->close() a second time when the process later unmaps the range,
+producing a reference count underflow.
+
+Replace both hard-error returns with a deferred-fault approach that keeps
+the VMA alive and retries page insertion through the HMM range-fault path.
+
+Fixes: e486147c912f ("accel/amdxdna: Add BO import and export")
+Reviewed-by: Max Zhen <max.zhen@amd.com>
+Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
+Link: https://patch.msgid.link/20260723074256.2435143-1-lizhi.hou@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/amdxdna/amdxdna_gem.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
+index cdf113dadc4db..41fb39d095749 100644
+--- a/drivers/accel/amdxdna/amdxdna_gem.c
++++ b/drivers/accel/amdxdna/amdxdna_gem.c
+@@ -371,6 +371,23 @@ static void amdxdna_gem_dev_obj_free(struct drm_gem_object *gobj)
+       amdxdna_gem_destroy_obj(abo);
+ }
++static void amdxdna_mark_mapp_invalid(struct amdxdna_gem_obj *abo,
++                                    struct vm_area_struct *vma)
++{
++      struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
++      struct amdxdna_umap *mapp;
++
++      down_write(&xdna->notifier_lock);
++      abo->mem.map_invalid = true;
++      list_for_each_entry(mapp, &abo->mem.umap_list, node) {
++              if (compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
++                      mapp->invalid = true;
++                      break;
++              }
++      }
++      up_write(&xdna->notifier_lock);
++}
++
+ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
+                               struct vm_area_struct *vma)
+ {
+@@ -392,8 +409,7 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
+                                     &num_pages);
+               if (ret) {
+                       XDNA_ERR(xdna, "Failed insert pages %d", ret);
+-                      vma->vm_ops->close(vma);
+-                      return ret;
++                      amdxdna_mark_mapp_invalid(abo, vma);
+               }
+               return 0;
+@@ -413,9 +429,9 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
+               fault_ret = handle_mm_fault(vma, vma->vm_start + offset,
+                                           FAULT_FLAG_WRITE, NULL);
+               if (fault_ret & VM_FAULT_ERROR) {
+-                      vma->vm_ops->close(vma);
+                       XDNA_ERR(xdna, "Fault in page failed");
+-                      return -EFAULT;
++                      amdxdna_mark_mapp_invalid(abo, vma);
++                      break;
+               }
+               offset += PAGE_SIZE;
+-- 
+2.53.0
+
diff --git a/queue-7.1/alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken-f.patch b/queue-7.1/alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken-f.patch
new file mode 100644 (file)
index 0000000..24ba3ec
--- /dev/null
@@ -0,0 +1,54 @@
+From 62d4903edd07f2261af2eabf583bf45ffee38393 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 21:45:05 +0800
+Subject: ALSA: usb-audio: Add QUIRK_FLAG_MIXER_GET_CUR_BROKEN for Logitech PRO
+ X 2 LIGHTSPEED
+
+From: Rong Zhang <i@rong.moe>
+
+[ Upstream commit c973e61895db8fe4a69d8b33de92068d135cafd8 ]
+
+The UAC mixer of the Logitech PRO X 2 LIGHTSPEED has broken mixer
+GET_CUR behavior but otherwise works fine.
+
+Add a quirk table entry matching VID/PID=0x046d/0x0af7 and apply the
+MIXER_GET_CUR_BROKEN quirk flag to make the mixer usable again.
+
+Quirky device sample (after applying the quirk flag):
+
+  usb 3-2.1: New USB device found, idVendor=046d, idProduct=0af7, bcdDevice= 1.00
+  usb 3-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
+  usb 3-2.1: Product: PRO X 2 LIGHTSPEED
+  usb 3-2.1: Manufacturer: Logitech
+  usb 3-2.1: SerialNumber: 0000000000000000
+  usb 3-2.1: 2:0: broken mixer GET_CUR (-18944/0/256 => -2662)
+  usb 3-2.1: 6:0: broken mixer GET_CUR (-18944/0/256 => 0)
+
+Fixes: 86aa1ea1f15c ("ALSA: usb-audio: Do not expose sticky mixers")
+Suggested-by: Brian van den Berg <faxuser@proton.me>
+Reported-by: Brian van den Berg <faxuser@proton.me>
+Link: https://lore.kernel.org/all/370007e6-b73b-4bfc-8410-a860781c7ad7@proton.me/
+Signed-off-by: Rong Zhang <i@rong.moe>
+Link: https://patch.msgid.link/20260731-uac-lg-pro-x-2-ls-v1-1-268eaefe66ab@rong.moe
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 688993bfa8fd1..e97038cf5271e 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2249,6 +2249,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+       DEVICE_FLG(0x046d, 0x0a8f, /* Logitech H390 headset */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M |
+                  QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
++      DEVICE_FLG(0x046d, 0x0af7, /* Logitech PRO X 2 LIGHTSPEED */
++                 QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
+       DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
+-- 
+2.53.0
+
diff --git a/queue-7.1/alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken.patch b/queue-7.1/alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken.patch
new file mode 100644 (file)
index 0000000..ca845a2
--- /dev/null
@@ -0,0 +1,264 @@
+From 31e783ee84c8e2a10849ab2e654f916f65a51df2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 23:45:20 +0800
+Subject: ALSA: usb-audio: Add QUIRK_FLAG_MIXER_GET_CUR_BROKEN
+
+From: Rong Zhang <i@rong.moe>
+
+[ Upstream commit ad2c7d2c42af943a3e711bdc1e4fd55b76fcbe55 ]
+
+Since commit 86aa1ea1f15c ("ALSA: usb-audio: Do not expose sticky
+mixers"), the UAC mixer core utilizes volume SET_CUR and GET_CUR to
+identify devices with sticky mixers. Unfortunately, even though most
+devices with sticky GET_CUR also have corresponding sticky SET_CUR,
+which I actually met more since the commit had been merged, there is
+also a rare case that some devices may have volume mixers that responds
+to SET_CUR properly but with its GET_CUR stubbed. This cause the sticky
+check to consider the mixer to be sticky and unnecessarily disable it.
+
+As the sticky check can't distinguish between sticky mixers and working
+SET_CUR but broken GET_CUR, add QUIRK_FLAG_MIXER_GET_CUR_BROKEN to tell
+that the device should fall into the second category when GET_CUR
+returns a constant value. In this case, the sticky check becomes
+non-fatal and only disables GET_CUR instead of the whole mixer. The
+current volume will then be provided by the internal cache that stores
+the last set volume.
+
+An info message prompting users to check MIXER_GET_CUR_BROKEN for
+potential sticky mixers is also added, so that users can learn how to do
+some experiments to determine what's going on. If the mixer surprisingly
+turns out to be non-sticky, they can submit a patch for a new quirk
+table entry.
+
+Signed-off-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260531-uac-quirk-get-cur-vol-v4-1-ede643dca151@rong.moe
+Stable-dep-of: c973e61895db ("ALSA: usb-audio: Add QUIRK_FLAG_MIXER_GET_CUR_BROKEN for Logitech PRO X 2 LIGHTSPEED")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/sound/alsa-configuration.rst | 12 +++++
+ sound/usb/mixer.c                          | 60 ++++++++++++++++++----
+ sound/usb/mixer.h                          |  1 +
+ sound/usb/quirks.c                         |  1 +
+ sound/usb/usbaudio.h                       | 13 +++++
+ 5 files changed, 77 insertions(+), 10 deletions(-)
+
+diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
+index 4b30cd63c5a5a..78fb484e8b04f 100644
+--- a/Documentation/sound/alsa-configuration.rst
++++ b/Documentation/sound/alsa-configuration.rst
+@@ -2389,6 +2389,18 @@ quirk_flags
+           from snd_usb_handle_sync_urb. Instead fall through and enqueue a
+           packet_info containing only size-0 packets, so the OUT ring keeps
+           moving (emits silence). Needed by Behringer Flow 8 (1397:050c).
++        * bit 30: ``mixer_get_cur_broken``
++          Some mixers are sticky, which means that setting their current volume
++          is a no-op, and reading the current volume returns a constant value.
++          The sticky check disables these mixers to prevent confusing userspace.
++          However, some devices do have a tunable volume despite the reported
++          current volume being constant. As the sticky check can't distinguish
++          between the two categories, setting this flag tells that the device
++          should fall into the second category when GET_CUR returns a constant
++          value, resulting in the sticky check being non-fatal and only
++          disabling GET_CUR instead of the whole mixer. The current volume will
++          then be provided by the internal cache that stores the last set
++          volume
+ This module supports multiple devices, autoprobe and hotplugging.
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index dbcefcaf7c361..142f5ca7a72d2 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -434,6 +434,11 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
+               *value = cval->cache_val[index];
+               return 0;
+       }
++
++      /* The current value is always provided by the cache after initialization. */
++      if (cval->get_cur_broken)
++              return -ENXIO;
++
+       err = get_cur_mix_raw(cval, channel, value);
+       if (err < 0) {
+               if (!cval->head.mixer->ignore_ctl_error)
+@@ -1234,7 +1239,7 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
+       err = snd_usb_get_cur_mix_value(cval, ch, idx, &val);
+       if (!err)
+               return;
+-      if (!cval->head.mixer->ignore_ctl_error)
++      if (!cval->head.mixer->ignore_ctl_error && !cval->get_cur_broken)
+               usb_audio_warn(cval->head.mixer->chip,
+                              "%d:%d: failed to get current value for ch %d (%d)\n",
+                              cval->head.id, mixer_ctrl_intf(cval->head.mixer),
+@@ -1248,8 +1253,16 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
+  * Some devices' volume control mixers are sticky, which accept SET_CUR but
+  * do absolutely nothing.
+  *
+- * Prevent sticky mixers from being registered, otherwise they confuses
+- * userspace and results in ineffective volume control.
++ * Check the return values of GET_CUR with different SET_CUR values. Consider
++ * the mixer as sticky if GET_CUR always returns a constant value.
++ *
++ * Some devices have effective SET_CUR despite GET_CUR being constant. Do not
++ * consider the mixer as sticky if a quirk flag indicates that.
++ *
++ * Gate the registration of sticky mixers to prevent confusing userspace, so
++ * that they won't cause ineffective volume control. However, for mixers with
++ * effective SET_CUR but broken GET_CUR, the registration can continue normally
++ * but further GET_CUR requests will be gated.
+  */
+ static int check_sticky_volume_control(struct usb_mixer_elem_info *cval,
+                                      int channel, int saved)
+@@ -1269,10 +1282,22 @@ static int check_sticky_volume_control(struct usb_mixer_elem_info *cval,
+                       return 0;
+       }
++      if (cval->head.mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_GET_CUR_BROKEN) {
++              usb_audio_info(cval->head.mixer->chip,
++                             "%d:%d: broken mixer GET_CUR (%d/%d/%d => %d)\n",
++                             cval->head.id, mixer_ctrl_intf(cval->head.mixer),
++                             cval->min, cval->max, cval->res, saved);
++
++              cval->get_cur_broken = 1;
++              return -ENXIO;
++      }
++
+       usb_audio_err(cval->head.mixer->chip,
+                     "%d:%d: sticky mixer values (%d/%d/%d => %d), disabling\n",
+                     cval->head.id, mixer_ctrl_intf(cval->head.mixer),
+                     cval->min, cval->max, cval->res, saved);
++      usb_audio_info(cval->head.mixer->chip,
++                     "check MIXER_GET_CUR_BROKEN if you believe the mixer is non-sticky");
+       return -ENODEV;
+ }
+@@ -1315,7 +1340,7 @@ static void check_volume_control_res(struct usb_mixer_elem_info *cval,
+ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+                                  int default_min, struct snd_kcontrol *kctl)
+ {
+-      int i, idx, ret;
++      int i, idx, ret = 0;
+       /* for failsafe */
+       cval->min = default_min;
+@@ -1371,8 +1396,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+                               goto no_checks;
+                       ret = check_sticky_volume_control(cval, minchn, saved);
+-                      if (ret < 0)
++                      if (ret == -ENODEV)
+                               goto sticky;
++                      if (ret)
++                              goto no_checks;
+                       if (cval->min + cval->res < cval->max)
+                               check_volume_control_res(cval, minchn, saved);
+@@ -1381,6 +1408,16 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+               }
+ no_checks:
++              /*
++               * Got a non-fatal failure during sanity checks.
++               *
++               * Do not propagate mixer values written by sanity checks.
++               * Instead, rely on init_cur_mix_raw() to initialize the mixer
++               * properly.
++               */
++              if (ret)
++                      cval->cached = 0;
++
+               cval->initialized = 1;
+       }
+@@ -3538,7 +3575,8 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
+                       continue;
+               info = mixer_elem_list_to_info(list);
+               /* invalidate cache, so the value is read from the device */
+-              info->cached = 0;
++              if (!info->get_cur_broken)
++                      info->cached = 0;
+               snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              &list->kctl->id);
+       }
+@@ -3635,10 +3673,12 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
+               switch (attribute) {
+               case UAC2_CS_CUR:
+                       /* invalidate cache, so the value is read from the device */
+-                      if (channel)
+-                              info->cached &= ~BIT(channel);
+-                      else /* master channel */
+-                              info->cached = 0;
++                      if (!info->get_cur_broken) {
++                              if (channel)
++                                      info->cached &= ~BIT(channel);
++                              else /* master channel */
++                                      info->cached = 0;
++                      }
+                       snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                      &info->head.kctl->id);
+diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
+index afbb3dd9f177b..3fa1bd96f8588 100644
+--- a/sound/usb/mixer.h
++++ b/sound/usb/mixer.h
+@@ -94,6 +94,7 @@ struct usb_mixer_elem_info {
+       int cache_val[MAX_CHANNELS];
+       u8 initialized;
+       u8 min_mute;
++      u8 get_cur_broken;
+       void *private_data;
+ };
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 33eb8be48af87..688993bfa8fd1 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2611,6 +2611,7 @@ static const char *const snd_usb_audio_quirk_flag_names[] = {
+       QUIRK_STRING_ENTRY(MIXER_PLAYBACK_LINEAR_VOL),
+       QUIRK_STRING_ENTRY(MIXER_CAPTURE_LINEAR_VOL),
+       QUIRK_STRING_ENTRY(IFB_SILENCE_ON_EMPTY),
++      QUIRK_STRING_ENTRY(MIXER_GET_CUR_BROKEN),
+       NULL
+ };
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index 9afcad8f143a0..e472aef6eb879 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -242,6 +242,17 @@ extern bool snd_usb_skip_validation;
+  *  from snd_usb_handle_sync_urb. Instead fall through and enqueue a
+  *  packet_info containing only size-0 packets, so the OUT ring keeps
+  *  moving (emits silence). Needed by Behringer Flow 8 (1397:050c).
++ * QUIRK_FLAG_MIXER_GET_CUR_BROKEN
++ *  Some mixers are sticky, which means that setting their current volume is a
++ *  no-op, and reading the current volume returns a constant value. The sticky
++ *  check disables these mixers to prevent confusing userspace. However, some
++ *  devices do have a tunable volume despite the reported current volume being
++ *  constant. As the sticky check can't distinguish between the two categories,
++ *  setting this flag tells that the device should fall into the second
++ *  category when GET_CUR returns a constant value, resulting in the sticky
++ *  check being non-fatal and only disabling GET_CUR instead of the whole mixer.
++ *  The current volume will then be provided by the internal cache that stores
++ *  the last set volume
+  */
+ enum {
+@@ -275,6 +286,7 @@ enum {
+       QUIRK_TYPE_MIXER_PLAYBACK_LINEAR_VOL    = 27,
+       QUIRK_TYPE_MIXER_CAPTURE_LINEAR_VOL     = 28,
+       QUIRK_TYPE_IFB_SILENCE_ON_EMPTY         = 29,
++      QUIRK_TYPE_MIXER_GET_CUR_BROKEN         = 30,
+ /* Please also edit snd_usb_audio_quirk_flag_names */
+ };
+@@ -310,5 +322,6 @@ enum {
+ #define QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL  QUIRK_FLAG(MIXER_PLAYBACK_LINEAR_VOL)
+ #define QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL   QUIRK_FLAG(MIXER_CAPTURE_LINEAR_VOL)
+ #define QUIRK_FLAG_IFB_SILENCE_ON_EMPTY               QUIRK_FLAG(IFB_SILENCE_ON_EMPTY)
++#define QUIRK_FLAG_MIXER_GET_CUR_BROKEN               QUIRK_FLAG(MIXER_GET_CUR_BROKEN)
+ #endif /* __USBAUDIO_H */
+-- 
+2.53.0
+
diff --git a/queue-7.1/alsa-usb-audio-fix-sticky-mixer-regressions-on-m-aud.patch b/queue-7.1/alsa-usb-audio-fix-sticky-mixer-regressions-on-m-aud.patch
new file mode 100644 (file)
index 0000000..8ea7c99
--- /dev/null
@@ -0,0 +1,48 @@
+From 6e863757289511922135720250dc384814df8d46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Aug 2026 10:34:16 +0200
+Subject: ALSA: usb-audio: Fix sticky mixer regressions on M-Audio Fast Track
+ Ultra
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit a8934c2c6dfd72901cf3cc0de28e85eb902a61a4 ]
+
+The recent fix for sticky mixer volumes caused regressions of M-audio
+Fast Track Ultra device, where the mixer state is kept to the default
+value.
+
+Add the quirk entries to tolerate the broken mixer behavior.  As the
+device is known to work in the implicit feedback mode, explicitly
+enable the implicit feedback mode, too.
+
+Since there are two FTU models that are almost identical, both entries
+are added in this patch (0763:2080 and 0763:2081).
+
+Fixes: 86aa1ea1f15c ("ALSA: usb-audio: Do not expose sticky mixers")
+Link: https://bugzilla.suse.com/show_bug.cgi?id=1273166
+Link: https://patch.msgid.link/20260807083418.1712585-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index e97038cf5271e..354866a806056 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2320,6 +2320,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x0763, 0x2031, /* M-Audio Fast Track C600 */
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
++      DEVICE_FLG(0x0763, 0x2080, /* M-Audio Fast Track Ultra */
++                 QUIRK_FLAG_MIXER_GET_CUR_BROKEN | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
++      DEVICE_FLG(0x0763, 0x2081, /* M-Audio Fast Track Ultra */
++                 QUIRK_FLAG_MIXER_GET_CUR_BROKEN | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x07fd, 0x000b, /* MOTU M Series 2nd hardware revision */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch b/queue-7.1/arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
new file mode 100644 (file)
index 0000000..c659287
--- /dev/null
@@ -0,0 +1,39 @@
+From b92154d6ef4536bac11fecaecbff73f2cf068ed6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 14:57:22 -0700
+Subject: ARM: dts: BCM5301X: fix PCIe controller 2 second interrupt
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit bab4d538f8485e0d48538fcb82b285df3779278e ]
+
+PCIe controller 2 has interrupts 0-4 mapping to GIC SPI 138-142. The
+mapping for interrupt 1 was incorrectly set to 138 due to a copy-paste
+error. Fix it to 139.
+
+Assisted-by: opencode:big-pickle
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://lore.kernel.org/r/20260725215722.9323-1-rosenp@gmail.com
+Fixes: 3b3e35b279be ("ARM: dts: BCM5301X: Relicense AXI interrupts code to the GPL 2.0+ / MIT")
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/broadcom/bcm-ns.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+index 392a257136696..bd52de0faa3ea 100644
+--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
++++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+@@ -141,7 +141,7 @@ axi@18000000 {
+                       /* PCIe Controller 2 */
+                       <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+-                      <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
++                      <0x00014000 1 &gic GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch b/queue-7.1/arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
new file mode 100644 (file)
index 0000000..2fd7e0a
--- /dev/null
@@ -0,0 +1,50 @@
+From 4283322924643de464c569c760a81eabcbf02d6d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 May 2026 23:38:46 -0400
+Subject: ARM: npcm: Fix OF node refcount leaks in SMP setup
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+[ Upstream commit 8eb052f48331474c2789d07b7f11165c323bd2f9 ]
+
+npcm7xx_smp_boot_secondary() and npcm7xx_smp_prepare_cpus() look up
+the GCR and SCU nodes with of_find_compatible_node(). The returned
+nodes are used for of_iomap(), but the node references are never
+released.
+
+of_iomap() does not consume the device node reference, and iounmap()
+only releases the MMIO mapping. Drop each node reference after the
+corresponding mapping attempt.
+
+Fixes: 7bffa14c9aed ("arm: npcm: add basic support for Nuvoton BMCs")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Avi Fishman <avifishman70@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-npcm/platsmp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-npcm/platsmp.c b/arch/arm/mach-npcm/platsmp.c
+index 41891d3aa1247..4c1fc9983746c 100644
+--- a/arch/arm/mach-npcm/platsmp.c
++++ b/arch/arm/mach-npcm/platsmp.c
+@@ -32,6 +32,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
+               goto out;
+       }
+       gcr_base = of_iomap(gcr_np, 0);
++      of_node_put(gcr_np);
+       if (!gcr_base) {
+               pr_err("could not iomap gcr");
+               ret = -ENOMEM;
+@@ -60,6 +61,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
+               return;
+       }
+       scu_base = of_iomap(scu_np, 0);
++      of_node_put(scu_np);
+       if (!scu_base) {
+               pr_err("could not iomap scu");
+               return;
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch b/queue-7.1/arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch
new file mode 100644 (file)
index 0000000..16c52bf
--- /dev/null
@@ -0,0 +1,52 @@
+From f0284b7aa6a3f1c0df86649cb21fce578350e432 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 21:45:27 +0100
+Subject: arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual
+ timer
+
+From: Daniel Drake <dan@reactivated.net>
+
+[ Upstream commit 75952cfc7752c52a2b692b59d34ce160d3edabb2 ]
+
+Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to EL2
+virtual timer when running VHE") causes boot to hang on Raspberry Pi 5.
+The newly-selected EL2 virtual timer does not generate any interrupts,
+even though the GIC_DIST_ENABLE_SET flag has been confirmed set via
+readback.
+
+It is highly unusual that this timer interrupt is non-operational because
+this is a standard GIC interrupt corresponding to a standard Cortex-A76
+CPU timer. However, Broadcom have confirmed for this SoC:
+
+> the interrupt line was never connected in the first place as this was
+> not identified as being a requirement
+
+Remove the corresponding DeviceTree entry.
+
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
+Fixes: faa3381267d0 ("arm64: dts: broadcom: Add minimal support for Raspberry Pi 5")
+Signed-off-by: Daniel Drake <dan@reactivated.net>
+Link: https://lore.kernel.org/r/20260716-bcm2712-el2-v2-1-e708f7fb42fa@reactivated.net
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+index 761c59d90ffc9..09ff5e9959d3a 100644
+--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
++++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+@@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
+                                         IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
+-                                        IRQ_TYPE_LEVEL_LOW)>,
+-                           <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
+                                         IRQ_TYPE_LEVEL_LOW)>;
+       };
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-qcom-glymur-fix-pcie-smmu-interrupts.patch b/queue-7.1/arm64-dts-qcom-glymur-fix-pcie-smmu-interrupts.patch
new file mode 100644 (file)
index 0000000..b6ca37b
--- /dev/null
@@ -0,0 +1,44 @@
+From c0b042d5b01bd95be979b30180d42672779e9887 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Jun 2026 19:00:44 +0000
+Subject: arm64: dts: qcom: glymur: fix PCIe SMMU interrupts
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+[ Upstream commit 52c7084c8fe57c259e50ff0a7d4f99ccecfc4c7a ]
+
+The PCIe SMMUv3 wired interrupts are routed to GIC extended SPI INTIDs
+4100, 4098 and 4096. Describe them as ESPIs with the ESPI-relative
+interrupt numbers instead of regular SPIs 964, 962 and 960.
+
+Assisted-by: Codex:GPT-5.5
+Fixes: 41b6e8db400c ("arm64: dts: qcom: Introduce Glymur base dtsi")
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260611-glymur-pcie-smmu-espi-v1-1-5effbaa3e1af@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/glymur.dtsi | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
+index 63df60b7e010e..468614d101c02 100644
+--- a/arch/arm64/boot/dts/qcom/glymur.dtsi
++++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
+@@ -5626,9 +5626,9 @@ apps_smmu: iommu@15000000 {
+               pcie_smmu: iommu@15480000 {
+                       compatible = "arm,smmu-v3";
+                       reg = <0x0 0x15480000 0x0 0x20000>;
+-                      interrupts = <GIC_SPI 964 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 962 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 960 IRQ_TYPE_LEVEL_HIGH>;
++                      interrupts = <GIC_ESPI 4 IRQ_TYPE_LEVEL_HIGH>,
++                                   <GIC_ESPI 2 IRQ_TYPE_LEVEL_HIGH>,
++                                   <GIC_ESPI 0 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "eventq", "cmdq-sync", "gerror";
+                       dma-coherent;
+                       #iommu-cells = <1>;
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-qcom-glymur-fix-qup-serial-engine-irqs.patch b/queue-7.1/arm64-dts-qcom-glymur-fix-qup-serial-engine-irqs.patch
new file mode 100644 (file)
index 0000000..a2856d7
--- /dev/null
@@ -0,0 +1,152 @@
+From 6a1e0e19ec5d51e27399651d1d965c8d070132c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Jun 2026 17:22:37 +0000
+Subject: arm64: dts: qcom: glymur: fix QUP serial engine IRQs
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+[ Upstream commit a74a98f956ef8e075f28d58507bc5dad7f937fb4 ]
+
+The Geni serial-engine interrupts from QUP wrapper 0 all fall in ESPI
+INTIDs space. While some of the i2c instances has gotten their
+interrupt specifiers corrected, even the other functions on the same
+serial-engines are wrong.
+
+Ensure that all the serial engine interrupts for QUP wrapper 0 matches
+the datasheet.
+
+Assisted-by: Codex:GPT-5.5
+Fixes: 41b6e8db400c ("arm64: dts: qcom: Introduce Glymur base dtsi")
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260611-glymur-geni-irqs-v1-1-269428faeb6d@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/glymur.dtsi | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
+index 468614d101c02..25df2bd06735d 100644
+--- a/arch/arm64/boot/dts/qcom/glymur.dtsi
++++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
+@@ -1843,7 +1843,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi0: spi@b80000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b80000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1052 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 92 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -1870,7 +1870,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       i2c1: i2c@b84000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x0 0x00b84000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1053 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 93 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -1897,7 +1897,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi1: spi@b84000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b84000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1053 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 93 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -1924,7 +1924,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       i2c2: i2c@b88000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x0 0x00b88000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -1951,7 +1951,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi2: spi@b88000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b88000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -1978,7 +1978,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       uart2: serial@b88000 {
+                               compatible = "qcom,geni-uart";
+                               reg = <0x0 0x00b88000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2023,7 +2023,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi3: spi@b8c000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b8c000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1055 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 95 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2077,7 +2077,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi4: spi@b90000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b90000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1056 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2131,7 +2131,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi5: spi@b94000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b94000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1057 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 97 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2158,7 +2158,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       i2c6: i2c@b98000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x0 0x00b98000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1058 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 98 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2185,7 +2185,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi6: spi@b98000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b98000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1058 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 98 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2212,7 +2212,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       i2c7: i2c@b9c000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x0 0x00b9c000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1059 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 99 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+@@ -2239,7 +2239,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+                       spi7: spi@b9c000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x0 0x00b9c000 0x0 0x4000>;
+-                              interrupts = <GIC_SPI 1059 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupts = <GIC_ESPI 99 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+                               clock-names = "se";
+                               interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-qcom-monaco-add-default-gic-address-cells.patch b/queue-7.1/arm64-dts-qcom-monaco-add-default-gic-address-cells.patch
new file mode 100644 (file)
index 0000000..d491e70
--- /dev/null
@@ -0,0 +1,48 @@
+From e0504d42d5fd9d51b83e56ca770ab5992e5ce3d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Apr 2026 22:15:19 +0200
+Subject: arm64: dts: qcom: monaco: Add default GIC address cells
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
+
+[ Upstream commit d291245e2fb1eba55d751f88613a41e292958a96 ]
+
+Add missing address-cells 0 to GIC interrupt node to silence W=1
+warning:
+
+  monaco.dtsi:2326.4-2329.30: Warning (interrupt_map): /soc@0/pci@1c00000:interrupt-map:
+    Missing property '#address-cells' in node /soc@0/interrupt-controller@17a00000, using 0 as fallback
+
+Value '0' is correct because:
+1. GIC interrupt controller does not have children,
+2. interrupt-map property (in PCI node) consists of five components and
+   the fourth component 'parent unit address', which size is defined by
+   '#address-cells' of the node pointed to by the interrupt-parent
+   component, is not used (=0).
+
+Fixes: 46a7c01e7e9d ("arm64: dts: qcom: qcs8300: enable pcie0")
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260407201518.24949-2-krzysztof.kozlowski@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/monaco.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
+index fa13210fc539a..62e6b60087ee3 100644
+--- a/arch/arm64/boot/dts/qcom/monaco.dtsi
++++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
+@@ -7384,6 +7384,7 @@ intc: interrupt-controller@17a00000 {
+                       interrupt-controller;
+                       #redistributor-regions = <1>;
+                       redistributor-stride = <0x0 0x20000>;
++                      #address-cells = <0>;
+               };
+               watchdog@17c10000 {
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch b/queue-7.1/arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch
new file mode 100644 (file)
index 0000000..3a9601e
--- /dev/null
@@ -0,0 +1,99 @@
+From b6e0397d1c682a29e784cd397d503e29e39fd1d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Apr 2026 02:38:51 +0530
+Subject: arm64: dts: qcom: purwa: Fix GPU IOMMU property
+
+From: Akhil P Oommen <akhilpo@oss.qualcomm.com>
+
+[ Upstream commit 4cd774c1feb3f720265c512174c5c3312eca1be2 ]
+
+Purwa's GPU does not support SID 1, which is typically used for
+LPAC-related traffic. Remove SID 1 from the GPU node's iommus property to
+accurately describe the hardware. This fixes the splat below, seen with
+some versions of Gunyah hypervisor:
+
+  Internal error: synchronous external abort: 0000000096000010 [#1]  SMP
+  CPU: 0 UID: 0 PID: 80 Comm: kworker/u33:2 Tainted: G   M
+  Tainted: [M]=MACHINE_CHECK
+  Hardware name: Qualcomm Technologies, Inc. Purwa IoT EVK (DT)
+  Workqueue: events_unbound deferred_probe_work_func
+  pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
+  pc : arm_smmu_write_s2cr+0x9c/0xbc
+  lr : arm_smmu_master_install_s2crs+0x78/0xa4
+  sp : ffff80008039b570
+  x29: ffff80008039b570 x28: 0000000000000000 x27: ffffaddd62f1ab78
+  x26: ffff00080a4ff280 x25: 0000000000000018 x24: ffff00080b896480
+  x23: ffff00080ba9b7a0 x22: ffff00080bb05160 x21: 0000000000000000
+  x20: 0000000000000000 x19: 0000000000000001 x18: 00000000ffffffff
+  x17: 0000000000000000 x16: 0000000000000000 x15: ffff80008039b1d0
+  x14: ffff80010039b37d x13: 00746c7561662d74 x12: 0000000000000000
+  x11: ffff00080b7fbd98 x10: ffffffffffffffc0 x9 : ffffffffffffffff
+  x8 : 0000000000000228 x7 : 0000000000000e87 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : ffff00080a4ff280 x3 : 0000000000000000
+  x2 : ffff800082a40c04 x1 : 0000000000000000 x0 : ffff800082a40000
+  Call trace:
+   arm_smmu_write_s2cr+0x9c/0xbc (P)
+   arm_smmu_master_install_s2crs+0x78/0xa4
+   arm_smmu_attach_dev+0xb0/0x1d8
+   __iommu_device_set_domain+0x84/0x11c
+   __iommu_group_set_domain_internal+0x60/0x120
+   __iommu_attach_group+0x88/0x9c
+   iommu_attach_device+0x6c/0xa0
+   msm_iommu_new.part.0+0x84/0xe4 [msm]
+   msm_iommu_gpu_new+0x3c/0x104 [msm]
+   adreno_iommu_create_vm+0x24/0xc8 [msm]
+   a6xx_create_vm+0x48/0x78 [msm]
+   msm_gpu_init+0x2d8/0x508 [msm]
+   adreno_gpu_init+0x208/0x324 [msm]
+   a6xx_gpu_init+0x604/0x8cc [msm]
+   adreno_bind+0xb4/0x124 [msm]
+   component_bind_all+0x114/0x23c
+   msm_drm_init+0x1b0/0x1ec [msm]
+   msm_drm_bind+0x30/0x3c [msm]
+   try_to_bring_up_aggregate_device+0x164/0x1d0
+   __component_add+0xa4/0x16c
+   component_add+0x14/0x20
+   msm_dp_display_probe_tail+0x4c/0xac [msm]
+   msm_dp_auxbus_done_probe+0x14/0x20 [msm]
+   dp_aux_ep_probe+0x4c/0xf4 [drm_dp_aux_bus]
+   really_probe+0xbc/0x29c
+   __driver_probe_device+0x78/0x12c
+   driver_probe_device+0x3c/0x15c
+   __device_attach_driver+0xb8/0x134
+   bus_for_each_drv+0x88/0xe8
+   __device_attach+0xa0/0x190
+   device_initial_probe+0x50/0x54
+   bus_probe_device+0x38/0xa4
+   deferred_probe_work_func+0x88/0xc0
+   process_one_work+0x148/0x28c
+   worker_thread+0x2cc/0x3d4
+   kthread+0x12c/0x204
+   ret_from_fork+0x10/0x20
+  ---[ end trace 0000000000000000 ]---
+
+Fixes: 1aa0b4e36436 ("arm64: dts: qcom: x1p42100: Add GPU support")
+Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260410-purwa-gpu-dt-fix-v1-1-4637892156cf@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/purwa.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi
+index 9ab4f26b35f29..5b17840fb62fb 100644
+--- a/arch/arm64/boot/dts/qcom/purwa.dtsi
++++ b/arch/arm64/boot/dts/qcom/purwa.dtsi
+@@ -47,6 +47,8 @@ &gmu {
+ &gpu {
+       compatible = "qcom,adreno-43030c00", "qcom,adreno";
++      iommus = <&adreno_smmu 0 0x0>;
++
+       nvmem-cells = <&gpu_speed_bin>;
+       nvmem-cell-names = "speed_bin";
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch b/queue-7.1/arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch
new file mode 100644 (file)
index 0000000..c8682ae
--- /dev/null
@@ -0,0 +1,45 @@
+From 61d5d2864edaf2976a1476344fe9bd64599b66d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 01:27:12 +0300
+Subject: arm64: dts: qcom: sdm850-lenovo-yoga-c630: lower PSCI cluster idle
+
+From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+
+[ Upstream commit 07db10de262f4150e24fd631a7a6c428f7bf80c9 ]
+
+With the default PSCI suspend value for cluster idle state Lenovo Yoga
+C630 isn't stable enough. For example it might reset if display device
+isn't probed early enough. Drop the bit 0x4000 from the PSCI suspend
+value to make C630 work in stable way. The bit was found by
+expertimenting with the cluster idle PSCI value. Most likely it results
+in the less deep sleep and more energy beign spent in the suspend state,
+but it's better than the non-stable system behaviour.
+
+Fixes: a1ade6cac5a2 ("arm64: dts: qcom: sdm845: Switch PSCI cpu idle states from PC to OSI")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260429-c630-fix-idle-v2-1-ac867dad6f21@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+index e41200839dbec..8cdaef5360d11 100644
+--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
++++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+@@ -347,6 +347,10 @@ &cdsp_pas {
+       status = "okay";
+ };
++&cluster_sleep_0 {
++      arm,psci-suspend-param = <0x41008244>;
++};
++
+ &gcc {
+       protected-clocks = <GCC_QSPI_CORE_CLK>,
+                          <GCC_QSPI_CORE_CLK_SRC>,
+-- 
+2.53.0
+
diff --git a/queue-7.1/arm64-dts-qcom-sm8650-fix-ipa-imem-slice.patch b/queue-7.1/arm64-dts-qcom-sm8650-fix-ipa-imem-slice.patch
new file mode 100644 (file)
index 0000000..78d5c6d
--- /dev/null
@@ -0,0 +1,42 @@
+From dd5583ad318c68e3e4bb9e3856cbc71e80c86d8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 23:45:18 +0000
+Subject: arm64: dts: qcom: sm8650: Fix IPA IMEM slice
+
+From: Alexander Koskovich <akoskovich@pm.me>
+
+[ Upstream commit 41d237b1546af5d5cf877175930cd23163422c83 ]
+
+Downstream the IPA IMEM slice for SM8650 is described as:
+qcom,additional-mapping = <0x14683000 0x14683000 0x2000>;
+
+Update upstream ipa_modem_tables to reflect downstream.
+
+Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
+Fixes: 581fc5d5ade6 ("arm64: dts: qcom: sm8650: Explicitly describe the IPA IMEM slice")
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260415-fix-8650-ipa-modem-tables-v1-1-95f8f425e416@pm.me
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8650.dtsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
+index e2d98cf6adca8..ecfa3478cbdde 100644
+--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
+@@ -7091,8 +7091,8 @@ sram@14680000 {
+                       ranges = <0 0 0x14680000 0x2c000>;
+-                      ipa_modem_tables: modem-tables@8000 {
+-                              reg = <0x8000 0x2000>;
++                      ipa_modem_tables: modem-tables@3000 {
++                              reg = <0x3000 0x2000>;
+                       };
+               };
+-- 
+2.53.0
+
diff --git a/queue-7.1/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch b/queue-7.1/ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
new file mode 100644 (file)
index 0000000..43a9813
--- /dev/null
@@ -0,0 +1,52 @@
+From 33df9dc6ef8524fae209c4067ab1f2f7ce88c2eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:28 +0800
+Subject: ata: pata_sl82c105: fix bridge revision use-after-free
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 7700a31039cdc6715cb6cce7e7a664ee4e945f67 ]
+
+pci_get_slot() returns a referenced PCI device. Commit 44c10138fd4b
+("PCI: Change all drivers to use pci_device->revision") replaced a
+configuration-space read with direct access to the cached revision field,
+but left that access after pci_dev_put(). The bridge may therefore be freed
+before its revision is read.
+
+Read the revision before dropping the reference.
+
+Fixes: 44c10138fd4b ("PCI: Change all drivers to use pci_device->revision")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_sl82c105.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 2d24c6b3e9d9f..25bce3fe2a101 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -264,6 +264,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ {
+       struct pci_dev *bridge;
++      u8 revision;
+       /*
+        * The bridge should be part of the same device, but function 0.
+@@ -285,8 +286,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+       /*
+        * We need to find function 0's revision, not function 1
+        */
++      revision = bridge->revision;
+       pci_dev_put(bridge);
+-      return bridge->revision;
++      return revision;
+ }
+ static void sl82c105_fixup(struct pci_dev *pdev)
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnge-fix-null-pointer-dereference-in-aux-device-rele.patch b/queue-7.1/bnge-fix-null-pointer-dereference-in-aux-device-rele.patch
new file mode 100644 (file)
index 0000000..a31a774
--- /dev/null
@@ -0,0 +1,58 @@
+From 851259a955366c9e483546cef17293e050c586b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:22:59 -0700
+Subject: bnge: Fix NULL pointer dereference in aux device release
+
+From: Alok Tiwari <alok.a.tiwari@oracle.com>
+
+[ Upstream commit 1cb4298810e27e037d3ca07286ecbb97e89ba58d ]
+
+If allocation of auxr_dev fails during auxiliary device setup, the error
+path calls auxiliary_device_uninit(), which eventually invokes
+bnge_aux_dev_release().
+
+The release callback unconditionally dereferences aux_priv->auxr_dev->pdev
+to retrieve the parent bnge_dev. Since auxr_dev has not yet been allocated
+on this failure path, the dereference results in a NULL pointer exception
+
+Retrieve the parent bnge_dev from the auxiliary device's parent instead of
+auxr_dev, and free auxr_dev only when it was successfully allocated. This
+allows the release callback to correctly clean up partially initialized
+auxiliary devices.
+
+Fixes: 8ac050ec3b1c ("bng_en: Add RoCE aux device support")
+Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
+Reviewed-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+Link: https://patch.msgid.link/20260731192301.1427645-1-alok.a.tiwari@oracle.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnge/bnge_auxr.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c b/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c
+index 67e93e17d4d9f..0955b488b6fea 100644
+--- a/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c
++++ b/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c
+@@ -141,12 +141,15 @@ static void bnge_aux_dev_release(struct device *dev)
+ {
+       struct bnge_auxr_priv *aux_priv =
+                       container_of(dev, struct bnge_auxr_priv, aux_dev.dev);
+-      struct bnge_dev *bd = pci_get_drvdata(aux_priv->auxr_dev->pdev);
++      struct bnge_auxr_dev *auxr_dev = aux_priv->auxr_dev;
++      struct bnge_dev *bd = pci_get_drvdata(to_pci_dev(dev->parent));
+       ida_free(&bnge_aux_dev_ids, aux_priv->id);
+-      kfree(aux_priv->auxr_dev->auxr_info);
++      if (auxr_dev) {
++              kfree(auxr_dev->auxr_info);
++              kfree(auxr_dev);
++      }
+       bd->auxr_dev = NULL;
+-      kfree(aux_priv->auxr_dev);
+       kfree(aux_priv);
+       bd->aux_priv = NULL;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch b/queue-7.1/bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch
new file mode 100644 (file)
index 0000000..8150f57
--- /dev/null
@@ -0,0 +1,42 @@
+From 067e01bda598d83db5fcb4eaab0e6cfa540bf643 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 15:10:22 +0530
+Subject: bnge: Fix resource leak in bnge_init_nic() error path
+
+From: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+
+[ Upstream commit bfec39ff1484b4e9f7d93bc4580fdb634bbc7d19 ]
+
+If bnge_init_chip() fails, bnge_init_nic() jumps to err_free_ring_grps
+and returns immediately, skipping cleanup for RX ring pair buffers.
+
+Remove the early return so execution falls through to
+err_free_rx_ring_pair_bufs to properly free resources on error.
+
+Fixes: 23df6aebf803 ("bng_en: Allocate stat contexts")
+Signed-off-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+Reviewed-by: Dharmender Garg <dharmender.garg@broadcom.com>
+Reviewed-by: Rajashekar Hudumula <rajashekar.hudumula@broadcom.com>
+Link: https://patch.msgid.link/20260805094022.15487-1-bhargava.marreddy@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnge/bnge_netdev.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
+index 6f7ef506d4e18..ac4c93e5b634a 100644
+--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
++++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
+@@ -2768,8 +2768,6 @@ static int bnge_init_nic(struct bnge_net *bn)
+ err_free_ring_grps:
+       bnge_free_ring_grps(bn);
+-      return rc;
+-
+ err_free_rx_ring_pair_bufs:
+       bnge_free_rx_ring_pair_bufs(bn);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnge-use-int-for-bnge_fix_rings_count-return-value.patch b/queue-7.1/bnge-use-int-for-bnge_fix_rings_count-return-value.patch
new file mode 100644 (file)
index 0000000..7bd603b
--- /dev/null
@@ -0,0 +1,44 @@
+From 4d7c07f17587437a6d726007f515d86766967ff2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 03:09:20 -0700
+Subject: bnge: use int for bnge_fix_rings_count() return value
+
+From: Alok Tiwari <alok.a.tiwari@oracle.com>
+
+[ Upstream commit 2cbd8a4e5e09aa232a1f8d56ce3d070b18ab2b10 ]
+
+bnge_fix_rings_count() returns 0 on success or a negative errno on failure
+However, bnge_adjust_rings() stores its return value in a u16 variable,
+causing negative error codes such as -ENOMEM to be converted to a large
+positive value.
+
+Use an int for the return code variable so that error values are
+preserved and propagated correctly.
+
+Fixes: 627c67f038d2 ("bng_en: Add resource management support")
+Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
+Reviewed-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
+Link: https://patch.msgid.link/20260801100923.1498570-1-alok.a.tiwari@oracle.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnge/bnge_resc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+index 0e94f092813e0..4711dd4945ffe 100644
+--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
++++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+@@ -163,7 +163,8 @@ static int bnge_adjust_rings(struct bnge_dev *bd, u16 *rx,
+       u16 tx_chunks = bnge_num_tx_to_cp(bd, *tx);
+       if (tx_chunks != *tx) {
+-              u16 tx_saved = tx_chunks, rc;
++              u16 tx_saved = tx_chunks;
++              int rc;
+               rc = bnge_fix_rings_count(rx, &tx_chunks, max_nq, sh);
+               if (rc)
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch b/queue-7.1/bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch
new file mode 100644 (file)
index 0000000..684ffee
--- /dev/null
@@ -0,0 +1,54 @@
+From 1200751616e5a1d1f77012aa17410aad6530e7de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:31 -0700
+Subject: bnxt: fix memory leak in bnxt_queue_mem_alloc error cases
+
+From: Will Chen <will.chen.tty@gmail.com>
+
+[ Upstream commit d1000fd7995e51deec872d154e0a40d82f7a539f ]
+
+There is a small memory leak in bnxt_queue_mem_alloc:
+when bnxt_alloc_rx_agg_bmap() succeeds
+but bnxt_alloc_one_tpa_info() later fails,
+the rx_agg_bmap allocated by bnxt_alloc_rx_agg_bmap()
+is not freed in the fallthrough cleanup cases.
+
+Free the rx_agg_bmap in the err_free_rx_agg_ring case
+and initialize clone->rx_agg_bmap = NULL earlier in the function
+to allow for safe fallthrough.
+
+Fixes: bd649c5cc958 ("bnxt_en: handle tpa_info in queue API implementation")
+Signed-off-by: Will Chen <will.chen.tty@gmail.com>
+Reviewed-by: Joe Damato <joe@dama.to>
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260729220132.1256924-1-will.chen.tty@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index d44d3ac255aa4..cb6e45fc9cd98 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -16225,6 +16225,7 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
+       clone->rx_next_cons = 0;
+       clone->need_head_pool = false;
+       clone->rx_page_size = qcfg->rx_page_size;
++      clone->rx_agg_bmap = NULL;
+       rc = bnxt_alloc_rx_page_pool(bp, clone, rxr->page_pool->p.nid);
+       if (rc)
+@@ -16277,6 +16278,8 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
+       bnxt_free_one_tpa_info(bp, clone);
+ err_free_rx_agg_ring:
+       bnxt_free_ring(bp, &clone->rx_agg_ring_struct.ring_mem);
++      kfree(clone->rx_agg_bmap);
++      clone->rx_agg_bmap = NULL;
+ err_free_rx_ring:
+       bnxt_free_ring(bp, &clone->rx_ring_struct.ring_mem);
+ err_rxq_info_unreg:
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch b/queue-7.1/bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch
new file mode 100644 (file)
index 0000000..900e305
--- /dev/null
@@ -0,0 +1,155 @@
+From 350f771fd0318644180a9243771678aa8bab9d91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:34 -0700
+Subject: bnxt_en: Determine and store default RX ring in vnic structure
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 53f01cd594e223aabb538d5288e60111523c96f2 ]
+
+Each VNIC has a default RX ring.  The purpose of the default RX ring
+is to provide a destination for any packets that cannot be parsed by
+the RSS logic.  Up until now, the default RX ring is always Ring 0.
+
+We neglected to take care of this default RX ring when adding the
+queue restart feature.  If ring 0 (default ring) is re-started, it
+may now have a new FW ring ID after freeing the old one and
+allocating a new one.  The VNIC now may have a stale default ring
+and it may generate an internal exception.  This exception may
+appear in dmesg:
+
+FW reported unknown error type 10
+
+The best way to resolve this issue is to use a more appropriate
+ring for the default ring instead of always ring 0.  Ring 0 may not
+even be in the RSS table, especially on a new RSS context.
+
+This patch adds the logic to determine and store the proper default
+RX ring for a VNIC.  For an RSS VNIC, the default ring is the lowest
+ring number in the RSS table.  The next patch will add proper logic
+to update the VNIC if the default ring changes after queue restart.
+
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-3-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0b137529a899 ("bnxt_en: Refresh VNIC default ring on queue restart if needed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 33 +++++++++++++++--------
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h |  1 +
+ 2 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 2fbc98fa14f62..4ea6adfc5c22a 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6704,25 +6704,36 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings)
+ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+ {
+       bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
+-      u16 i, j;
++      u16 i, j, min_j = bp->rx_nr_rings - 1;
+       if (!vnic->rss_table)
+-              return;
++              goto skip_rss_tbl;
+       /* Fill the RSS indirection table with ring group ids */
+       for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+               if (!no_rss)
+                       j = bp->rss_indir_tbl[i];
++              min_j = min(j, min_j);
+               vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]);
+       }
++
++skip_rss_tbl:
++      if (vnic->rss_table && !no_rss)
++              vnic->default_rx_ring = min_j;
++      else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
++              vnic->default_rx_ring = vnic->vnic_id - 1;
++      else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
++              vnic->default_rx_ring = bp->rx_nr_rings - 1;
++      else
++              vnic->default_rx_ring = 0;
+ }
+ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+                                   struct bnxt_vnic_info *vnic)
+ {
++      u16 tbl_size, i, min_j = bp->rx_nr_rings - 1;
+       __le16 *ring_tbl = vnic->rss_table;
+       struct bnxt_rx_ring_info *rxr;
+-      u16 tbl_size, i;
+       tbl_size = bnxt_get_rxfh_indir_size(bp->dev);
+@@ -6735,6 +6746,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+                       j = ethtool_rxfh_context_indir(vnic->rss_ctx)[i];
+               else
+                       j = bp->rss_indir_tbl[i];
++              min_j = min(j, min_j);
+               rxr = &bp->rx_ring[j];
+               ring_id = rxr->rx_ring_struct.fw_ring_id;
+@@ -6742,6 +6754,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
+               ring_id = bnxt_cp_ring_for_rx(bp, rxr);
+               *ring_tbl++ = cpu_to_le16(ring_id);
+       }
++      vnic->default_rx_ring = min_j;
+ }
+ static void
+@@ -6938,8 +6951,9 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+               return rc;
+       if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+-              struct bnxt_rx_ring_info *rxr = &bp->rx_ring[0];
++              struct bnxt_rx_ring_info *rxr;
++              rxr = &bp->rx_ring[vnic->default_rx_ring];
+               req->default_rx_ring_id =
+                       cpu_to_le16(rxr->rx_ring_struct.fw_ring_id);
+               req->default_cmpl_ring_id =
+@@ -6972,13 +6986,7 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+               req->cos_rule = cpu_to_le16(0xffff);
+       }
+-      if (vnic->flags & BNXT_VNIC_RSS_FLAG)
+-              ring = 0;
+-      else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
+-              ring = vnic->vnic_id - 1;
+-      else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
+-              ring = bp->rx_nr_rings - 1;
+-
++      ring = vnic->default_rx_ring;
+       grp_idx = bp->rx_ring[ring].bnapi->index;
+       req->dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id);
+       req->lb_rule = cpu_to_le16(0xffff);
+@@ -11171,6 +11179,9 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt *bp)
+               return rc;
+       }
++      /* Setup the proper default RX ring */
++      bnxt_fill_hw_rss_tbl(bp, vnic);
++
+       rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+       if (rc) {
+               netdev_err(bp->dev, "Cannot allocate special vnic for NS2 A0: %x\n",
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index fa13cee557798..8e04cc934c32b 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -1334,6 +1334,7 @@ struct bnxt_vnic_info {
+ #define BNXT_VNIC_RSSCTX_FLAG         0x40
+       struct ethtool_rxfh_context *rss_ctx;
+       u32             vnic_id;
++      u16             default_rx_ring;
+ };
+ struct bnxt_rss_ctx {
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch b/queue-7.1/bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
new file mode 100644 (file)
index 0000000..0f7c44e
--- /dev/null
@@ -0,0 +1,57 @@
+From 194d0e47a3648717069a69ee40a69793a20823b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:36 -0700
+Subject: bnxt_en: Disable EOP for TPA on all chips to prevent data corruption
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit c3faf548a00f4c17100cc9204746975fa46a73b9 ]
+
+EOP (End of frame padding) on the AGG ring may cause overlapping of
+zero padding at the end of one segment with the next segment's data.
+If Relaxed Ordering (RO) is enabled, the zero padding may overwrite
+valid data in the next segment and corrupt the data.  Older chips
+(P5 and older) do not automatically disable RO when EOP is enabled.
+On some ARM systems, data corruption was reported on 57508 (P5)
+chips with RO enabled.
+
+Always disable EOP on all chips on the AGG rings when TPA is enabled
+to fix the data corruption.
+
+Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index e7145537f3e73..1cd6e88d4e814 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -4611,11 +4611,14 @@ static void bnxt_init_one_rx_agg_ring_rxbd(struct bnxt *bp,
+               type = ((u32)rxr->rx_page_size << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD;
+-              /* On P7, setting EOP will cause the chip to disable
+-               * Relaxed Ordering (RO) for TPA data.  Disable EOP for
+-               * potentially higher performance with RO.
++              /* Disable EOP if TPA is enabled to prevent overlapping zero
++               * padding with the next segment's data.  On P7_PLUS, EOP will
++               * automatically disable Relaxed Ordering (RO) to prevent
++               * potential data corruption (and may degrade performance).  On
++               * older chips, RO will not be automatically disabled and may
++               * cause corruption.
+                */
+-              if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA))
++              if (!(bp->flags & BNXT_FLAG_TPA))
+                       type |= RX_BD_FLAGS_AGG_EOP;
+               bnxt_init_rxbd_pages(ring, type);
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnxt_en-fix-ptp-pps-setting-bug.patch b/queue-7.1/bnxt_en-fix-ptp-pps-setting-bug.patch
new file mode 100644 (file)
index 0000000..679c5e2
--- /dev/null
@@ -0,0 +1,54 @@
+From c983bb02d31d9dd3d292f3069a856ec5f961ec5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:37 -0700
+Subject: bnxt_en: Fix PTP PPS setting bug
+
+From: Keegan Freyhof <keegan.freyhof@broadcom.com>
+
+[ Upstream commit 80eaf88efec33ac77ed7726d066c4f2f932cc329 ]
+
+The existing driver logic is always turning on PTP_CLK_REQ_PPS
+regardless of the "on" parameter passed to bnxt_ptp_enable().
+During shutdown, PTP_CLK_REQ_PPS may be turned off and this
+bug will do the opposite and may trigger a PCIe PTM request TLP.
+On some systems this can trigger a PCIe AER.
+
+Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on"
+parameter.
+
+Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+index 5d41dc1bc7820..b89293dfd2d1e 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+@@ -495,12 +495,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info,
+               return rc;
+       case PTP_CLK_REQ_PPS:
+               /* Configure PHC PPS IN */
+-              rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN);
++              pin_id = 0;
++              if (!on)
++                      break;
++              rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN);
+               if (rc)
+                       return rc;
+               rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL);
+               if (!rc)
+-                      ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL;
++                      ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL;
+               return rc;
+       default:
+               netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch b/queue-7.1/bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch
new file mode 100644 (file)
index 0000000..6537d9d
--- /dev/null
@@ -0,0 +1,75 @@
+From 8e27366cbe015e104fcd13086e80361b8f0151a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:33 -0700
+Subject: bnxt_en: Move RSS table fill outside __bnxt_hwrm_vnic_set_rss()
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 1d0fc6c7ea49994b8ff50d02979d1e4207ec6c4f ]
+
+This is a refactor patch with no change in behavior.  The caller
+will now fill the RSS table before calling __bnxt_hwrm_vnic_set_rss().
+In the next patch, we'll add code to determine the default ring for
+the VNIC when we fill the RSS table.
+
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-2-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0b137529a899 ("bnxt_en: Refresh VNIC default ring on queue restart if needed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index cb6e45fc9cd98..2fbc98fa14f62 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6706,6 +6706,9 @@ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+       bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
+       u16 i, j;
++      if (!vnic->rss_table)
++              return;
++
+       /* Fill the RSS indirection table with ring group ids */
+       for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+               if (!no_rss)
+@@ -6745,13 +6748,8 @@ static void
+ __bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req,
+                        struct bnxt_vnic_info *vnic)
+ {
+-      if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+-              bnxt_fill_hw_rss_tbl_p5(bp, vnic);
+-              if (bp->flags & BNXT_FLAG_CHIP_P7)
+-                      req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
+-      } else {
+-              bnxt_fill_hw_rss_tbl(bp, vnic);
+-      }
++      if (bp->flags & BNXT_FLAG_CHIP_P7)
++              req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
+       if (bp->rss_hash_delta) {
+               req->hash_type = cpu_to_le32(bp->rss_hash_delta);
+@@ -6803,6 +6801,7 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp,
+       if (!set_rss)
+               return hwrm_req_send(bp, req);
++      bnxt_fill_hw_rss_tbl_p5(bp, vnic);
+       __bnxt_hwrm_vnic_set_rss(bp, req, vnic);
+       ring_tbl_map = vnic->rss_table_dma_addr;
+       nr_ctxs = bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings);
+@@ -10866,6 +10865,7 @@ static int __bnxt_setup_vnic(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+       }
+ skip_rss_ctx:
++      bnxt_fill_hw_rss_tbl(bp, vnic);
+       /* configure default vnic, ring grp */
+       rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+       if (rc) {
+-- 
+2.53.0
+
diff --git a/queue-7.1/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch b/queue-7.1/bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch
new file mode 100644 (file)
index 0000000..482187f
--- /dev/null
@@ -0,0 +1,46 @@
+From 2480bc4ab31d47c5b49b9e9aff79bc8cdf3bbe29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:09:35 -0700
+Subject: bnxt_en: Refresh VNIC default ring on queue restart if needed
+
+From: Shravya KN <shravya.k-n@broadcom.com>
+
+[ Upstream commit 0b137529a8997caf67190ca1d71ba8bbdb44fbfb ]
+
+When a queue is restarted, refresh VNIC_CFG for all VNICs whose
+default RX ring is the restarted ring.  This will eliminate this
+possible FW warning caused by a stale default ring in the VNIC:
+
+FW reported unknown error type 10
+
+Fixes: 5ac066b7b062 ("bnxt_en: Fix queue start to update vnic RSS table")
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20260731190937.807270-4-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 4ea6adfc5c22a..e7145537f3e73 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -11098,6 +11098,11 @@ static int bnxt_set_vnic_mru_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic,
+                                  vnic->vnic_id, rc);
+                       return rc;
+               }
++              if (rxr_id == vnic->default_rx_ring) {
++                      rc = bnxt_hwrm_vnic_cfg(bp, vnic);
++                      if (rc)
++                              return rc;
++              }
+       }
+       vnic->mru = mru;
+       bnxt_hwrm_vnic_update(bp, vnic,
+-- 
+2.53.0
+
diff --git a/queue-7.1/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch b/queue-7.1/bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
new file mode 100644 (file)
index 0000000..8987607
--- /dev/null
@@ -0,0 +1,80 @@
+From ee79950d43091222dc6e901c19361f695a0c9afe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2026 23:39:30 +0000
+Subject: bonding: alb: re-check primary_is_promisc under RTNL in
+ bond_alb_monitor
+
+From: Xiang Mei (Microsoft) <xmei5@asu.edu>
+
+[ Upstream commit 683c6ba6e58e6ed1037831ea97dd58d9c0e76b8d ]
+
+bond_alb_monitor() reads primary_is_promisc under RCU, then drops RCU and
+takes RTNL via rtnl_trylock() before undoing the promiscuity it set on the
+active slave. In that window the active slave can change under RTNL
+(RTM_DELLINK -> __bond_release_one() -> bond_alb_handle_active_change()),
+which already drops the promiscuity and clears primary_is_promisc. The
+monitor still acts on the stale decision: if the slave was removed with no
+failover, curr_active_slave is now NULL and the deref faults; if it failed
+over, the stale dev_set_promiscuity(-1) underflows the new slave's
+promiscuity counter and pins it in IFF_PROMISC.
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+  Workqueue: b42 bond_alb_monitor
+  RIP: 0010:bond_alb_monitor (drivers/net/bonding/bond_alb.c:1600)
+   process_one_work (kernel/workqueue.c:3322)
+   worker_thread (kernel/workqueue.c:3486)
+   kthread (kernel/kthread.c:436)
+   ret_from_fork (arch/x86/kernel/process.c:158)
+  Kernel panic - not syncing: Fatal exception
+
+Re-check primary_is_promisc (and curr_active_slave) after taking RTNL so
+the monitor only undoes an increment it still owns. The other bonding
+monitors already re-read state under RTNL in their commit phase
+(bond_miimon_commit/bond_ab_arp_commit); bond_alb_monitor() was the only
+one acting on the pre-trylock decision.
+
+Fixes: d0e81b7e2246 ("bonding: Acquire correct locks in alb for promisc change")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260725233930.2957317-1-xmei5@asu.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_alb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 2d37b07c8215c..839f7482dc182 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -1534,8 +1534,8 @@ void bond_alb_monitor(struct work_struct *work)
+       struct bonding *bond = container_of(work, struct bonding,
+                                           alb_work.work);
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
++      struct slave *slave, *curr;
+       struct list_head *iter;
+-      struct slave *slave;
+       if (!bond_has_slaves(bond)) {
+               atomic_set(&bond_info->tx_rebalance_counter, 0);
+@@ -1597,9 +1597,11 @@ void bond_alb_monitor(struct work_struct *work)
+                        * because a slave was disabled then
+                        * it can now leave promiscuous mode.
+                        */
+-                      dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+-                                          -1);
+-                      bond_info->primary_is_promisc = 0;
++                      curr = rtnl_dereference(bond->curr_active_slave);
++                      if (bond_info->primary_is_promisc && curr) {
++                              dev_set_promiscuity(curr->dev, -1);
++                              bond_info->primary_is_promisc = 0;
++                      }
+                       rtnl_unlock();
+                       rcu_read_lock();
+-- 
+2.53.0
+
diff --git a/queue-7.1/bpf-check-sk_state-before-sk_protocol-in-bpf_tcp_-_s.patch b/queue-7.1/bpf-check-sk_state-before-sk_protocol-in-bpf_tcp_-_s.patch
new file mode 100644 (file)
index 0000000..6b10b9f
--- /dev/null
@@ -0,0 +1,57 @@
+From a5d5175879d9f58a9de17888de75188f41ca70a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 22:29:01 +0800
+Subject: bpf: Check sk_state before sk_protocol in bpf_tcp_*_syncookie
+
+From: Luxiao Xu <rakukuip@gmail.com>
+
+[ Upstream commit 31a420a822ff92e2090bd5d65efe8e34e2d6d9b8 ]
+
+bpf_tcp_gen_syncookie and bpf_tcp_check_syncookie accept a socket pointer
+'sk' with argument type ARG_PTR_TO_BTF_ID_SOCK_COMMON. However, they access
+sk->sk_protocol without validating whether 'sk' represents a full socket.
+
+Fix this issue by checking sk->sk_state != TCP_LISTEN before inspecting
+sk->sk_protocol in both bpf_tcp_gen_syncookie and bpf_tcp_check_syncookie.
+Since mini-sockets are never in the TCP_LISTEN state, the condition
+short-circuits and prevents dereferencing fullsock-specific fields.
+
+Fixes: 399040847084 ("bpf: add helper to check for a valid SYN cookie")
+Fixes: 70d66244317e ("bpf: add bpf_tcp_gen_syncookie helper")
+Reported-by: Vega <vega@nebusec.ai>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://lore.kernel.org/bpf/6218aa3534d0d2d3f448fde70a8dc2769d7a8201.1785823138.git.rakukuip@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/filter.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 66837e93d3f25..233adfdc1c340 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -7645,7 +7645,7 @@ BPF_CALL_5(bpf_tcp_check_syncookie, struct sock *, sk, void *, iph, u32, iph_len
+               return -EINVAL;
+       /* sk_listener() allows TCP_NEW_SYN_RECV, which makes no sense here. */
+-      if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
++      if (sk->sk_state != TCP_LISTEN || sk->sk_protocol != IPPROTO_TCP)
+               return -EINVAL;
+       if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syncookies))
+@@ -7718,7 +7718,7 @@ BPF_CALL_5(bpf_tcp_gen_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
+       if (unlikely(!sk || th_len < sizeof(*th) || th_len != th->doff * 4))
+               return -EINVAL;
+-      if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
++      if (sk->sk_state != TCP_LISTEN || sk->sk_protocol != IPPROTO_TCP)
+               return -EINVAL;
+       if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syncookies))
+-- 
+2.53.0
+
diff --git a/queue-7.1/bpf-fix-netns-reference-imbalance-in-conntrack-kfunc.patch b/queue-7.1/bpf-fix-netns-reference-imbalance-in-conntrack-kfunc.patch
new file mode 100644 (file)
index 0000000..b886bc2
--- /dev/null
@@ -0,0 +1,209 @@
+From 1b11dcb8a320b9256b87cc7ba103e0642aa397da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 00:09:21 +0800
+Subject: bpf: Fix netns reference imbalance in conntrack kfuncs
+
+From: Chengfeng Ye <nicoyip.dev@gmail.com>
+
+[ Upstream commit fdeba03fea78407a8c52faa99177c9f7f29f90eb ]
+
+The opts argument of the BPF conntrack kfuncs can point to a shared
+map value.  __bpf_nf_ct_lookup() and __bpf_nf_ct_alloc_entry() read
+opts->netns_id separately when acquiring and releasing the network
+namespace reference.
+
+The reference imbalance can occur as follows:
+
+  CPU 0                                  CPU 1
+  read opts->netns_id (-1)
+  skip get_net_ns_by_id()
+                                         write opts->netns_id (id)
+  read opts->netns_id (id)
+  put_net(net) /* no matching get */
+
+The reverse transition leaks the reference.  Repeating the unmatched put
+can destroy a live namespace and crash later users.
+
+The kernel reported:
+
+  Oops: general protection fault, probably for non-canonical address
+  KASAN: null-ptr-deref in range [0x00000000000000e8-0x00000000000000ef]
+  RIP: 0010:bpf_prog_test_run_xdp+0x52c/0x1700
+  Call Trace:
+   __sys_bpf+0x1662/0x50c0
+   __x64_sys_bpf+0x73/0xb0
+   do_syscall_64+0xf9/0x540
+   entry_SYSCALL_64_after_hwframe+0x77/0x7f
+  Kernel panic - not syncing: Fatal exception
+
+Snapshot every input field of opts with READ_ONCE() before validating or
+using it.  The netns_id snapshot keeps the namespace get/put pair
+balanced, while the other snapshots keep the remaining options from
+changing partway through an invocation.  The individual reads can still
+observe an inconsistent combination during a concurrent update, but each
+selected field value remains stable for that invocation.
+
+Fixes: aed8ee7feb44 ("net: netfilter: Deduplicate code in bpf_{xdp,skb}_ct_lookup")
+Fixes: d7e79c97c00c ("net: netfilter: Add kfuncs to allocate and insert CT")
+Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
+Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
+Link: https://lore.kernel.org/bpf/20260731160921.3245840-1-nicoyip.dev@gmail.com
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_bpf.c | 72 +++++++++++++++++++++-----------
+ 1 file changed, 48 insertions(+), 24 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_bpf.c b/net/netfilter/nf_conntrack_bpf.c
+index f98d1d4b42c3d..c2df7c9482812 100644
+--- a/net/netfilter/nf_conntrack_bpf.c
++++ b/net/netfilter/nf_conntrack_bpf.c
+@@ -122,42 +122,54 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
+       struct nf_conntrack_tuple otuple, rtuple;
+       struct nf_conntrack_zone ct_zone;
+       struct nf_conn *ct;
++      u8 ct_zone_dir = 0;
++      u16 ct_zone_id;
++      s32 netns_id;
++      u8 l4proto;
+       int err;
+       if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12))
+               return ERR_PTR(-EINVAL);
++
++      netns_id = READ_ONCE(opts->netns_id);
++      l4proto = READ_ONCE(opts->l4proto);
++      ct_zone_id = READ_ONCE(opts->ct_zone_id);
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+-              if (opts->reserved[0] || opts->reserved[1] || opts->reserved[2])
++              ct_zone_dir = READ_ONCE(opts->ct_zone_dir);
++              if (READ_ONCE(opts->reserved[0]) ||
++                  READ_ONCE(opts->reserved[1]) ||
++                  READ_ONCE(opts->reserved[2]))
+                       return ERR_PTR(-EINVAL);
+       } else {
+-              if (opts->ct_zone_id)
++              if (ct_zone_id)
+                       return ERR_PTR(-EINVAL);
+       }
+-      if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
++      if (unlikely(netns_id < BPF_F_CURRENT_NETNS))
+               return ERR_PTR(-EINVAL);
+-      err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto,
++      err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, l4proto,
+                                   IP_CT_DIR_ORIGINAL, &otuple);
+       if (err < 0)
+               return ERR_PTR(err);
+-      err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto,
++      err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, l4proto,
+                                   IP_CT_DIR_REPLY, &rtuple);
+       if (err < 0)
+               return ERR_PTR(err);
+-      if (opts->netns_id >= 0) {
+-              net = get_net_ns_by_id(net, opts->netns_id);
++      if (netns_id >= 0) {
++              net = get_net_ns_by_id(net, netns_id);
+               if (unlikely(!net))
+                       return ERR_PTR(-ENONET);
+       }
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+-              if (opts->ct_zone_dir == 0)
+-                      opts->ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR;
+-              nf_ct_zone_init(&ct_zone,
+-                              opts->ct_zone_id, opts->ct_zone_dir, 0);
++              if (ct_zone_dir == 0) {
++                      ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR;
++                      opts->ct_zone_dir = ct_zone_dir;
++              }
++              nf_ct_zone_init(&ct_zone, ct_zone_id, ct_zone_dir, 0);
+       } else {
+               ct_zone = nf_ct_zone_dflt;
+       }
+@@ -171,7 +183,7 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
+       __nf_ct_set_timeout(ct, timeout * HZ);
+ out:
+-      if (opts->netns_id >= 0)
++      if (netns_id >= 0)
+               put_net(net);
+       return ct;
+@@ -186,46 +198,58 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
+       struct nf_conntrack_tuple tuple;
+       struct nf_conntrack_zone ct_zone;
+       struct nf_conn *ct;
++      u8 ct_zone_dir = 0;
++      u16 ct_zone_id;
++      s32 netns_id;
++      u8 l4proto;
+       int err;
+       if (!opts || !bpf_tuple)
+               return ERR_PTR(-EINVAL);
+       if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12))
+               return ERR_PTR(-EINVAL);
++
++      netns_id = READ_ONCE(opts->netns_id);
++      l4proto = READ_ONCE(opts->l4proto);
++      ct_zone_id = READ_ONCE(opts->ct_zone_id);
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+-              if (opts->reserved[0] || opts->reserved[1] || opts->reserved[2])
++              ct_zone_dir = READ_ONCE(opts->ct_zone_dir);
++              if (READ_ONCE(opts->reserved[0]) ||
++                  READ_ONCE(opts->reserved[1]) ||
++                  READ_ONCE(opts->reserved[2]))
+                       return ERR_PTR(-EINVAL);
+       } else {
+-              if (opts->ct_zone_id)
++              if (ct_zone_id)
+                       return ERR_PTR(-EINVAL);
+       }
+-      if (unlikely(opts->l4proto != IPPROTO_TCP && opts->l4proto != IPPROTO_UDP))
++      if (unlikely(l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP))
+               return ERR_PTR(-EPROTO);
+-      if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
++      if (unlikely(netns_id < BPF_F_CURRENT_NETNS))
+               return ERR_PTR(-EINVAL);
+-      err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto,
++      err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, l4proto,
+                                   IP_CT_DIR_ORIGINAL, &tuple);
+       if (err < 0)
+               return ERR_PTR(err);
+-      if (opts->netns_id >= 0) {
+-              net = get_net_ns_by_id(net, opts->netns_id);
++      if (netns_id >= 0) {
++              net = get_net_ns_by_id(net, netns_id);
+               if (unlikely(!net))
+                       return ERR_PTR(-ENONET);
+       }
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+-              if (opts->ct_zone_dir == 0)
+-                      opts->ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR;
+-              nf_ct_zone_init(&ct_zone,
+-                              opts->ct_zone_id, opts->ct_zone_dir, 0);
++              if (ct_zone_dir == 0) {
++                      ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR;
++                      opts->ct_zone_dir = ct_zone_dir;
++              }
++              nf_ct_zone_init(&ct_zone, ct_zone_id, ct_zone_dir, 0);
+       } else {
+               ct_zone = nf_ct_zone_dflt;
+       }
+       hash = nf_conntrack_find_get(net, &ct_zone, &tuple);
+-      if (opts->netns_id >= 0)
++      if (netns_id >= 0)
+               put_net(net);
+       if (!hash)
+               return ERR_PTR(-ENOENT);
+-- 
+2.53.0
+
diff --git a/queue-7.1/bpf-preserve-pointer-state-for-commuted-arithmetic.patch b/queue-7.1/bpf-preserve-pointer-state-for-commuted-arithmetic.patch
new file mode 100644 (file)
index 0000000..8bb23ee
--- /dev/null
@@ -0,0 +1,74 @@
+From 5163f7ec698d791ab29f954522bf13e93fb6c8ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:28 +0000
+Subject: bpf: Preserve pointer state for commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit a4c6f804b44c5c790269b25e0e61cf4e9f117c86 ]
+
+When scalar += pointer is handled in adjust_ptr_min_max_vals(), the
+destination register inherits the pointer state from the source pointer.
+Copying only selected fields is fragile because pointer provenance is
+tracked by several bpf_reg_state fields.
+
+Use the caller's temporary offset register to preserve the scalar operand
+while replacing the destination with the full pointer state. This preserves
+the frame number for PTR_TO_STACK registers and keeps parent identity
+fields consistent.
+
+Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-2-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 523f00e609e2b..ab88988d483d2 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -13837,11 +13837,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
+-       * The id may be overwritten later if we create a new variable offset.
++      /* For 'scalar += pointer', dst_reg inherits the complete pointer
++       * register state. Individual fields may be adjusted later by pointer
++       * arithmetic. Callers guarantee that below does not overwrite off_reg.
+        */
+-      dst_reg->type = ptr_reg->type;
+-      dst_reg->id = ptr_reg->id;
++      if (dst_reg != ptr_reg)
++              *dst_reg = *ptr_reg;
+       if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
+@@ -13893,7 +13894,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               break;
+       case BPF_SUB:
+-              if (dst_reg == off_reg) {
++              if (dst_reg != ptr_reg) {
+                       /* scalar -= pointer.  Creates an unknown scalar */
+                       verbose(env, "R%d tried to subtract pointer from scalar\n",
+                               dst);
+@@ -15137,8 +15138,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
+                               err = mark_chain_precision(env, insn->dst_reg);
+                               if (err)
+                                       return err;
+-                              return adjust_ptr_min_max_vals(env, insn,
+-                                                             src_reg, dst_reg);
++                              off_reg = *dst_reg;
++                              return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
+                       }
+               } else if (ptr_reg) {
+                       /* pointer += scalar */
+-- 
+2.53.0
+
diff --git a/queue-7.1/bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch b/queue-7.1/bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch
new file mode 100644 (file)
index 0000000..3881242
--- /dev/null
@@ -0,0 +1,59 @@
+From 2027d045fd3797c2842e48603b1cbb20f9a9d295 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:18:29 +0000
+Subject: bpf: Propagate untrusted pointer state in commuted arithmetic
+
+From: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+
+[ Upstream commit cdf19b1b3c01791de074ce282089131026f52261 ]
+
+The untrusted PTR_TO_MEM early return skips pointer offset tracking
+because accesses go through probe-read handling. Moving it after full
+pointer-state propagation ensures scalar += untrusted_pointer leaves the
+destination as PTR_TO_MEM instead of an unrelated scalar.
+
+Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
+Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
+Tested-by: Daniel Wade <danjwade95@gmail.com>
+Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-3-8ee297e2346b@mails.tsinghua.edu.cn
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index ab88988d483d2..5bad71f003dcc 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -13801,13 +13801,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      /*
+-       * Accesses to untrusted PTR_TO_MEM are done through probe
+-       * instructions, hence no need to track offsets.
+-       */
+-      if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
+-              return 0;
+-
+       switch (base_type(ptr_reg->type)) {
+       case PTR_TO_CTX:
+       case PTR_TO_MAP_VALUE:
+@@ -13844,6 +13837,13 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+       if (dst_reg != ptr_reg)
+               *dst_reg = *ptr_reg;
++      /*
++       * Accesses to untrusted PTR_TO_MEM are done through probe
++       * instructions, hence no need to track offsets.
++       */
++      if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
++              return 0;
++
+       if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
+           !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
+               return -EINVAL;
+-- 
+2.53.0
+
diff --git a/queue-7.1/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch b/queue-7.1/bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
new file mode 100644 (file)
index 0000000..1136f34
--- /dev/null
@@ -0,0 +1,170 @@
+From 7ad64f3a887853151edde8d3a317b75ff5a6f51f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:32:47 +0000
+Subject: bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()
+
+From: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+
+[ Upstream commit e5fd3f514e27db1f05fbd72ba615d74941e23c51 ]
+
+reqsk_queue_hash_req() publishes a TCP_NEW_SYN_RECV request_sock onto
+the ehash chain, drops the bucket lock, and only afterwards sets
+rsk_refcnt to 3.
+
+Lockless readers such as __inet_lookup_established() handle this with
+refcount_inc_not_zero(), but bpf_iter_tcp_established_batch() uses plain
+sock_hold() while holding the bucket lock, on the assumption that the
+lock guarantees sk_refcnt > 0. That assumption does not hold for
+request_sock:
+
+  CPU 0                                CPU 1
+  -----                                -----
+  tcp_conn_request()
+   reqsk_queue_hash_req()
+    inet_ehash_insert(req)
+     spin_lock(bucket)
+     __sk_nulls_add_node_rcu(req)      // rsk_refcnt == 0
+     spin_unlock(bucket)
+                                       bpf_iter_tcp_established_batch()
+                                        spin_lock(bucket)
+                                        sock_hold(req)   <-- addition on 0
+                                        spin_unlock(bucket)
+    refcount_set(&req->rsk_refcnt, 3)  // clobbers saturated value
+
+which surfaces as:
+
+  refcount_t: addition on 0; use-after-free.
+  WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x48/0x90, CPU#1
+  Call Trace:
+   bpf_iter_tcp_established_batch+0x14e/0x170
+   bpf_iter_tcp_batch+0x53/0x200
+   bpf_iter_tcp_seq_next+0x27/0x70
+   bpf_seq_read+0x107/0x410
+   vfs_read+0xb9/0x380
+
+The iterator's stolen reference is lost when the publishing CPU's
+refcount_set() overwrites the count, leaving the socket one reference
+short. When the last legitimate owner drops its reference the reqsk is
+freed while still reachable, leading to use-after-free.
+
+This reproduces in seconds with tcp_syncookies=0, a handful of threads
+doing connect()/close() to a local listener while others read an
+iter/tcp link in a tight loop.
+
+Use refcount_inc_not_zero() and skip the socket on failure. A skipped
+socket is still part of the bucket, so keep counting it in expected.
+The reallocations are sized from expected, and a request sock whose
+refcount gets published while the lock is held across the last realloc
+must already have room.
+
+A skipped socket is counted in expected but never batched, so end_sk
+can be short of expected on a batch that is actually complete. Decide
+completeness by whether the walk left any socket behind instead. The
+WARN after the locked realloc checks the same, replacing an
+end_sk == expected check that could not hold on that path since
+commit cdec67a489d4 ("bpf: tcp: Make sure iter->batch always
+contains a full bucket snapshot").
+
+If every matching socket in a bucket is mid-init (refcount 0), end_sk
+stays 0. Advance to the next bucket rather than returning a batch entry
+that was never filled this round.
+
+Fixes: 04c7820b776f ("bpf: tcp: Bpf iter batching and lock_sock")
+Assisted-by: Claude:unspecified
+Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://lore.kernel.org/bpf/20260730-bpf-iter-tcp-refcnt-v3-1-754b9c8a6717@linux.dev
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 43 ++++++++++++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 19 deletions(-)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index ce572025eeeba..4b59d258c2667 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -3079,24 +3079,24 @@ static unsigned int bpf_iter_tcp_established_batch(struct seq_file *seq,
+ {
+       struct bpf_tcp_iter_state *iter = seq->private;
+       struct hlist_nulls_node *node;
+-      unsigned int expected = 1;
+-      struct sock *sk;
+-
+-      sock_hold(*start_sk);
+-      iter->batch[iter->end_sk++].sk = *start_sk;
++      struct sock *sk = *start_sk;
++      unsigned int expected = 0;
+-      sk = sk_nulls_next(*start_sk);
+       *start_sk = NULL;
+       sk_nulls_for_each_from(sk, node) {
+-              if (seq_sk_match(seq, sk)) {
+-                      if (iter->end_sk < iter->max_sk) {
+-                              sock_hold(sk);
+-                              iter->batch[iter->end_sk++].sk = sk;
+-                      } else if (!*start_sk) {
+-                              /* Remember where we left off. */
+-                              *start_sk = sk;
+-                      }
+-                      expected++;
++              if (!seq_sk_match(seq, sk))
++                      continue;
++              expected++;
++              if (iter->end_sk < iter->max_sk) {
++                      /* reqsk_queue_hash_req() inserts with sk_refcnt == 0
++                       * and refcount_set()s it after the bucket lock drops.
++                       */
++                      if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
++                              continue;
++                      iter->batch[iter->end_sk++].sk = sk;
++              } else if (!*start_sk) {
++                      /* Remember where we left off. */
++                      *start_sk = sk;
+               }
+       }
+@@ -3134,12 +3134,13 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+       struct sock *sk;
+       int err;
++again:
+       sk = bpf_iter_tcp_resume(seq);
+       if (!sk)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was too small. */
+@@ -3158,7 +3159,7 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return NULL; /* Done */
+       expected = bpf_iter_fill_batch(seq, &sk);
+-      if (likely(iter->end_sk == expected))
++      if (likely(!sk))
+               goto done;
+       /* Batch size was still too small. Hold onto the lock while we try
+@@ -3171,10 +3172,14 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)
+               return ERR_PTR(err);
+       }
+-      expected = bpf_iter_fill_batch(seq, &sk);
+-      WARN_ON_ONCE(iter->end_sk != expected);
++      bpf_iter_fill_batch(seq, &sk);
++      WARN_ON_ONCE(sk);
+ done:
+       bpf_iter_tcp_unlock_bucket(seq);
++      if (unlikely(!iter->end_sk)) {
++              ++iter->state.bucket;
++              goto again;
++      }
+       return iter->batch[0].sk;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch b/queue-7.1/btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch
new file mode 100644 (file)
index 0000000..5de456e
--- /dev/null
@@ -0,0 +1,67 @@
+From 57fed36c720dac94ba6dde7a0adf00a0d2babf52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 16:37:39 +0930
+Subject: btrfs: disable bs > ps support if no transparent hugepage support
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 4c375ac546ea667e619ab77d34cca6edcab7c448 ]
+
+Btrfs relies on mapping_set_folio_order_range() to set the minimal
+folio order for all its data inodes, but that function will be no-op if
+transparent hugepage is not enabled.
+
+Guard the bs > ps support behind CONFIG_TRANSPARENT_HUGEPAGE, just like
+all other filesystems.
+
+Fixes: 98077f7f2180 ("btrfs: enable experimental bs > ps support")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/Kconfig |  3 ++-
+ fs/btrfs/fs.c    | 12 ++++++++++--
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
+index 55eba4f1b6c79..e1931281dddd0 100644
+--- a/fs/btrfs/Kconfig
++++ b/fs/btrfs/Kconfig
+@@ -110,7 +110,8 @@ config BTRFS_EXPERIMENTAL
+         - extent tree v2 - complex rework of extent tracking
+-        - block size > page size support
++        - block size > page size support - needs transparent huge page and
++                                           non-HIGHMEM system
+         - asynchronous checksum generation for data writes
+diff --git a/fs/btrfs/fs.c b/fs/btrfs/fs.c
+index 14d83565cdee1..dcf12979af33c 100644
+--- a/fs/btrfs/fs.c
++++ b/fs/btrfs/fs.c
+@@ -166,9 +166,17 @@ bool __attribute_const__ btrfs_supported_blocksize(u32 blocksize)
+        *
+        * Considering HIGHMEM is such a pain to deal with and it's going
+        * to be deprecated eventually, just reject HIGHMEM && bs > ps cases.
++       *
++       * Finally, for bs > ps cases, we need to set the minimal folio order,
++       * which requires transparent hugepage.
+        */
+-      if (IS_ENABLED(CONFIG_HIGHMEM) && blocksize > PAGE_SIZE)
+-              return false;
++      if (blocksize > PAGE_SIZE) {
++              if (IS_ENABLED(CONFIG_HIGHMEM))
++                      return false;
++
++              if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
++                      return false;
++      }
+       return true;
+ #endif
+       return false;
+-- 
+2.53.0
+
diff --git a/queue-7.1/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch b/queue-7.1/btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
new file mode 100644 (file)
index 0000000..793a16f
--- /dev/null
@@ -0,0 +1,96 @@
+From b842fef77217aeecac1baa74ea1bccd2a3aff47d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 14:53:52 +0300
+Subject: btrfs: fix memory leak in btrfs_do_encoded_write()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit d2a4e4e626b2f4670b69b430c357f03f53eb6632 ]
+
+Local fuzzing of 6.12.94 has found the following memory leak:
+
+Unreferenced object 0xffff888018050a80 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 10 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
+    10 0a 05 18 80 88 ff ff 10 0a 05 18 80 88 ff ff  ................
+  backtrace (crc a8a6fc29):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    extent_changeset_alloc fs/btrfs/extent_io.h:207 [inline]
+    qgroup_reserve_data+0x1c5/0x7d0 fs/btrfs/qgroup.c:4305
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Unreferenced object 0xffff888018050a00 (size 64):
+  comm "syz.0.17", pid 10297, jiffies 4294953601
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 ff 0f 00 00 00 00 00 00  ................
+    90 0a 05 18 80 88 ff ff 90 0a 05 18 80 88 ff ff  ................
+  backtrace (crc cb5c9580):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
+    slab_post_alloc_hook mm/slub.c:4152 [inline]
+    slab_alloc_node mm/slub.c:4197 [inline]
+    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
+    kmalloc_noprof include/linux/slab.h:878 [inline]
+    kzalloc_noprof include/linux/slab.h:1014 [inline]
+    ulist_prealloc+0x9c/0x110 fs/btrfs/ulist.c:114
+    extent_changeset_prealloc fs/btrfs/extent_io.h:217 [inline]
+    __set_extent_bit+0x16b/0x1a70 fs/btrfs/extent-io-tree.c:1086
+    set_record_extent_bits+0x50/0x90 fs/btrfs/extent-io-tree.c:1821
+    qgroup_reserve_data+0x274/0x7d0 fs/btrfs/qgroup.c:4312
+    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
+    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
+    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
+    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
+    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
+    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
+    vfs_ioctl fs/ioctl.c:51 [inline]
+    __do_sys_ioctl fs/ioctl.c:906 [inline]
+    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
+    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
+    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fix this by freeing an extent changeset before returning from
+btrfs_do_encoded_write().
+
+Fixes: 7c0c7269f7b5 ("btrfs: add BTRFS_IOC_ENCODED_WRITE")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index dc5148f176e77..a953d47eb2dd5 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -10193,6 +10193,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
+       if (cb)
+               cleanup_compressed_bio(cb);
+ out:
++      extent_changeset_free(data_reserved);
+       if (ret >= 0)
+               iocb->ki_pos += encoded->len;
+       return ret;
+-- 
+2.53.0
+
diff --git a/queue-7.1/btrfs-initialize-inode-mapping-flags-for-cached-inod.patch b/queue-7.1/btrfs-initialize-inode-mapping-flags-for-cached-inod.patch
new file mode 100644 (file)
index 0000000..a408dcc
--- /dev/null
@@ -0,0 +1,127 @@
+From d4bccdeceb398dc1b1b18d5db2e7b790ecba3adb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:14:49 +0930
+Subject: btrfs: initialize inode mapping flags for cached inodes
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 0ef349734a93227b45f65fc50a3311d1cc5f03e9 ]
+
+[BUG]
+When running generic/795 with 8K block size, 4K page size, the test
+always fails, triggering some ASSERT()s related to folio size:
+
+  795 (241074): drop_caches: 3
+  assertion failed: IS_ALIGNED(start, blocksize) && IS_ALIGNED(end + 1, blocksize), in extent_io.c:1404 (blocksize=8192 root=262 ino=258 start=16826368 end=16830463 mapping min order=0)
+  ------------[ cut here ]------------
+  kernel BUG at extent_io.c:1404!
+  Oops: invalid opcode: 0000 [#1] SMP
+  CPU: 8 UID: 0 PID: 241105 Comm: fsstress Tainted: G           OE       7.2.0-rc5-custom+ #442 PREEMPT(full)  f4bfb352566f3949f29c233ce6f735050a03b245
+  Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
+  RIP: 0010:assert_folio_range.cold+0x3d/0x3f [btrfs]
+  Call Trace:
+   <TASK>
+   btrfs_read_folio+0x9e/0x170 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
+   prepare_one_folio.constprop.0+0x104/0x2a0 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
+   btrfs_buffered_write+0x285/0xa50 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
+   btrfs_do_write_iter+0x1aa/0x210 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
+   iter_file_splice_write+0x31a/0x540
+   direct_splice_actor+0x53/0x170
+   splice_direct_to_actor+0xe9/0x240
+   do_splice_direct+0x76/0xb0
+   vfs_copy_file_range+0x1fd/0x630
+   __x64_sys_copy_file_range+0xf9/0x220
+   do_syscall_64+0xe1/0x790
+   entry_SYSCALL_64_after_hwframe+0x4b/0x53
+   </TASK>
+  ---[ end trace 0000000000000000 ]---
+
+The ASSERT() itself is added by a later patch.
+The crash is triggered with that new debug patch, and without this fix.
+
+[CAUSE]
+In the above case, the start 16826368 is properly 8K aligned, but the
+end (16830463 + 1) is not 8K aligned.
+Furthermore the mapping's minimal folio order is 0, not the expected 1
+for 8K block size with 4K page size.
+
+So this means some inodes do not have btrfs_set_inode_mapping_order()
+called on it.
+
+The missing btrfs_set_inode_mapping_order() call happens for cached
+inodes, through the following events:
+
+- btrfs_create_new_inode() called for inode X
+  Which properly sets minimal folio order for the VFS inode.
+
+- btrfs_update_inode() called for inode X
+  Which calls btrfs_delayed_update_inode() to create a delayed_node
+  into root->delayed_nodes xarray.
+
+- Drop cache/memory pressure, evicting in-memory inode X
+  Which evicted the inode X, but delayed_node is still in
+  root->delayed_nodes for future reuse.
+
+- btrfs_iget() for inode X called again
+
+  btrfs_iget()
+  |- btrfs_iget_locked()
+  |  |- iget5_locked_rcu()
+  |     Which creates a new vfs_inode for btrfs, whose mapping still
+  |     has the minimal order as 0.
+  |
+  |- btrfs_read_locked_inode()
+     |- btrfs_fill_inode()
+     |  |- btrfs_get_delayed_node()
+     |     Which found out the previous node, and use that delayed
+     |     node to initialize the new inode.
+     |
+     |- filled = true;
+     |- if (filled) goto cache_index;
+        Which skips the btrfs_update_inode_mapping_flags() and
+       btrfs_set_inode_mapping_order() calls.
+       So the inode still has minimal folio order set as 0, not
+       the required 1.
+
+Thus later page cache read will get a folio whose size is smaller than
+block size, as the mapping has its minimal folio order set as 0 not 1,
+then trigger the ASSERT().
+
+[FIX]
+Move the btrfs_update_inode_mapping_flags() and
+btrfs_set_inode_mapping_order() calls under cache_index label,
+so that the mapping flags and minimal folio order is always set
+no matter if we have a cached inode.
+
+Assisted-by: LLM (analysis)
+Fixes: ecde48a1a6b3 ("btrfs: expose per-inode stable writes flag")
+Fixes: cc38d178ff33 ("btrfs: enable large data folio support under CONFIG_BTRFS_EXPERIMENTAL")
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index a953d47eb2dd5..1271be0fbfcfa 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4167,10 +4167,11 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path
+       btrfs_inode_split_flags(btrfs_inode_flags(leaf, inode_item),
+                               &inode->flags, &inode->ro_flags);
++
++cache_index:
+       btrfs_update_inode_mapping_flags(inode);
+       btrfs_set_inode_mapping_order(inode);
+-cache_index:
+       /*
+        * If we were modified in the current generation and evicted from memory
+        * and then re-read we need to do a full sync since we don't have any
+-- 
+2.53.0
+
diff --git a/queue-7.1/btrfs-lzo-add-error-message-for-invalid-headers.patch b/queue-7.1/btrfs-lzo-add-error-message-for-invalid-headers.patch
new file mode 100644 (file)
index 0000000..c7618c5
--- /dev/null
@@ -0,0 +1,64 @@
+From 735303f7de97f12cab6ab47f21ae361672432c8d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jun 2026 08:23:49 +0930
+Subject: btrfs: lzo: add error message for invalid headers
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 1cb15b153c636096740519f62040ec6dc3e50aef ]
+
+Inside btrfs we always pair -EUCLEAN error with an error message to
+indicate which data is corrupted.
+
+However there are 3 cases inside lzo decompression where there is no
+error message for corrupted headers.
+
+Add those missing error messages to show exactly where the corruption
+is.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 0fa78ef637de ("btrfs: lzo: reject inline extents without valid headers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/lzo.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
+index 6e4aa22853aba..1531adb117d15 100644
+--- a/fs/btrfs/lzo.c
++++ b/fs/btrfs/lzo.c
+@@ -552,17 +552,26 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in,
+       size_t max_segment_len = workspace_buf_length(fs_info);
+       int ret;
+-      if (unlikely(srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2))
++      if (unlikely(srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)) {
++              btrfs_err(fs_info, "invalid lzo header length, has %zu expect (%u, %zu)",
++                        srclen, LZO_LEN, max_segment_len + LZO_LEN * 2);
+               return -EUCLEAN;
++      }
+       in_len = get_unaligned_le32(data_in);
+-      if (unlikely(in_len != srclen))
++      if (unlikely(in_len != srclen)) {
++              btrfs_err(fs_info, "invalid lzo header length, has %zu expect %zu",
++                        in_len, srclen);
+               return -EUCLEAN;
++      }
+       data_in += LZO_LEN;
+       in_len = get_unaligned_le32(data_in);
+-      if (unlikely(in_len != srclen - LZO_LEN * 2))
++      if (unlikely(in_len != srclen - LZO_LEN * 2)) {
++              btrfs_err(fs_info, "invalid lzo segment length, has %zu expect %zu",
++                        in_len, srclen - LZO_LEN * 2);
+               return -EUCLEAN;
++      }
+       data_in += LZO_LEN;
+       out_len = sectorsize;
+-- 
+2.53.0
+
diff --git a/queue-7.1/btrfs-lzo-reject-inline-extents-without-valid-header.patch b/queue-7.1/btrfs-lzo-reject-inline-extents-without-valid-header.patch
new file mode 100644 (file)
index 0000000..42fe277
--- /dev/null
@@ -0,0 +1,94 @@
+From d82242b80c354beb82b569d5e1ec89bd20ed48a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 09:05:14 +0000
+Subject: btrfs: lzo: reject inline extents without valid headers
+
+From: David Lee <david.lee@trailofbits.com>
+
+[ Upstream commit 0fa78ef637deb5dbe341582f88553a4bce496de0 ]
+
+[BUG]
+For a crafted btrfs image, the following KASAN can be triggered when
+reading an inline lzo compressed file extent:
+
+  BUG: KASAN: slab-out-of-bounds in lzo_decompress+0x57d/0x700
+  Read of size 4 at addr ffff888006f2e644 by task btrfs_lzo_inlin/77
+
+  Call Trace:
+   <TASK>
+   dump_stack_lvl+0x5b/0x70
+   print_report+0xd1/0x610
+   kasan_report+0xe0/0x110
+   __asan_report_load_n_noabort+0x13/0x20
+   lzo_decompress+0x57d/0x700
+   btrfs_decompress+0x140/0x1c0
+   uncompress_inline+0x147/0x1b0
+   btrfs_get_extent+0xb23/0x10a0
+   btrfs_do_readpage.constprop.0+0x538/0x1ac0
+   btrfs_readahead+0x32f/0x5f0
+   read_pages+0x16f/0x850
+   page_cache_ra_unbounded+0x296/0x490
+   do_page_cache_ra+0xd9/0x130
+   page_cache_sync_ra+0x3ee/0x6f0
+   filemap_get_pages+0x306/0x15c0
+   filemap_read+0x329/0xd00
+   btrfs_file_read_iter+0x1f8/0x2b0
+   vfs_read+0x4ef/0x720
+   ksys_read+0xf8/0x1d0
+   __x64_sys_read+0x71/0xb0
+   x64_sys_call+0x1ab0/0x1b70
+   do_syscall_64+0x61/0x470
+   entry_SYSCALL_64_after_hwframe+0x4b/0x53
+   </TASK>
+
+[CAUSE]
+For an inline lzo compressed file extent, there should always be one lzo
+header, recording the total length of the compressed data, followed by
+one segment header, recording the compressed lzo payload.
+
+But if a crafted inline lzo compressed file extent contains only an lzo
+header, without the segment header or payload, lzo_decompress() will
+still try to read the segment header, causing a read beyond the item
+boundary.
+
+Furthermore if the inline lzo compressed file extent is the first item
+of the leaf, it will be at the extent buffer boundary. The above
+out-of-boundary read will go beyond the extent buffer boundary,
+triggering the above KASAN report.
+
+[FIX]
+Validate the total length of the inlined lzo compressed file extent, to
+make sure there is at least one LZO header and one segment header, and a
+non-zero payload.
+
+Fixes: a6fa6fae40ec ("btrfs: Add lzo compression support")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: David Lee <david.lee@trailofbits.com>
+[ Rework the commit message to remove slop ]
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/lzo.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
+index 1531adb117d15..2f0996692da05 100644
+--- a/fs/btrfs/lzo.c
++++ b/fs/btrfs/lzo.c
+@@ -552,9 +552,10 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in,
+       size_t max_segment_len = workspace_buf_length(fs_info);
+       int ret;
+-      if (unlikely(srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)) {
++      if (unlikely(srclen <= LZO_LEN * 2 ||
++                   srclen > max_segment_len + LZO_LEN * 2)) {
+               btrfs_err(fs_info, "invalid lzo header length, has %zu expect (%u, %zu)",
+-                        srclen, LZO_LEN, max_segment_len + LZO_LEN * 2);
++                        srclen, LZO_LEN * 2, max_segment_len + LZO_LEN * 2);
+               return -EUCLEAN;
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/btrfs-move-large-data-folios-out-of-experimental-fea.patch b/queue-7.1/btrfs-move-large-data-folios-out-of-experimental-fea.patch
new file mode 100644 (file)
index 0000000..b8a6688
--- /dev/null
@@ -0,0 +1,96 @@
+From 3d8483065b9a103c8f10a57dd8638ce0f29b1dba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Apr 2026 10:20:25 +0930
+Subject: btrfs: move large data folios out of experimental features
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 9bce95edb1b4d2802de9273b5170bfcff3090d24 ]
+
+This feature was introduced in v6.17 under experimental, and we had
+several small bugs related to or exposed by that:
+
+  e9e3b22ddfa7 ("btrfs: fix beyond-EOF write handling")
+  18de34daa7c6 ("btrfs: truncate ordered extent when skipping writeback past i_size")
+
+Otherwise, the feature has been frequently tested by btrfs developers.
+
+The latest fix only arrived in v6.19. After three releases, I think it's
+time to move this feature out of experimental.
+
+And since we're here, also remove the comment about the bitmap size
+limit, which is no longer relevant in the context. It will soon be
+outdated for the incoming huge folio support.
+
+Reviewed-by: Neal Gompa <neal@gompa.dev>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 4c375ac546ea ("btrfs: disable bs > ps support if no transparent hugepage support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/Kconfig       |  2 +-
+ fs/btrfs/btrfs_inode.h |  3 ---
+ fs/btrfs/defrag.c      | 17 -----------------
+ 3 files changed, 1 insertion(+), 21 deletions(-)
+
+diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
+index 5e75438e0b738..55eba4f1b6c79 100644
+--- a/fs/btrfs/Kconfig
++++ b/fs/btrfs/Kconfig
+@@ -110,7 +110,7 @@ config BTRFS_EXPERIMENTAL
+         - extent tree v2 - complex rework of extent tracking
+-        - large folio and block size (> page size) support
++        - block size > page size support
+         - asynchronous checksum generation for data writes
+diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
+index beb75f152d5cd..8a802e3675cd8 100644
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -533,12 +533,9 @@ static inline void btrfs_set_inode_mapping_order(struct btrfs_inode *inode)
+       /* Metadata inode should not reach here. */
+       ASSERT(is_data_inode(inode));
+-      /* We only allow BITS_PER_LONGS blocks for each bitmap. */
+-#ifdef CONFIG_BTRFS_EXPERIMENTAL
+       mapping_set_folio_order_range(inode->vfs_inode.i_mapping,
+                                     inode->root->fs_info->block_min_order,
+                                     inode->root->fs_info->block_max_order);
+-#endif
+ }
+ void btrfs_calculate_block_csum_folio(struct btrfs_fs_info *fs_info,
+diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
+index 7e2db5d3a4d4c..9111308351f82 100644
+--- a/fs/btrfs/defrag.c
++++ b/fs/btrfs/defrag.c
+@@ -859,23 +859,6 @@ static struct folio *defrag_prepare_one_folio(struct btrfs_inode *inode, pgoff_t
+       if (IS_ERR(folio))
+               return folio;
+-      /*
+-       * Since we can defragment files opened read-only, we can encounter
+-       * transparent huge pages here (see CONFIG_READ_ONLY_THP_FOR_FS).
+-       *
+-       * The IO for such large folios is not fully tested, thus return
+-       * an error to reject such folios unless it's an experimental build.
+-       *
+-       * Filesystem transparent huge pages are typically only used for
+-       * executables that explicitly enable them, so this isn't very
+-       * restrictive.
+-       */
+-      if (!IS_ENABLED(CONFIG_BTRFS_EXPERIMENTAL) && folio_test_large(folio)) {
+-              folio_unlock(folio);
+-              folio_put(folio);
+-              return ERR_PTR(-ETXTBSY);
+-      }
+-
+       ret = set_folio_extent_mapped(folio);
+       if (ret < 0) {
+               folio_unlock(folio);
+-- 
+2.53.0
+
diff --git a/queue-7.1/counter-microchip-tcb-capture-fix-dt-channel-validat.patch b/queue-7.1/counter-microchip-tcb-capture-fix-dt-channel-validat.patch
new file mode 100644 (file)
index 0000000..4e66e4e
--- /dev/null
@@ -0,0 +1,70 @@
+From 9b1857ea19a74ca7e4d9eaa93dd5ff57deec855b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 04:29:10 +0000
+Subject: counter: microchip-tcb-capture: Fix DT channel validation
+
+From: Babanpreet Singh <bbnpreetsingh@gmail.com>
+
+[ Upstream commit f1a3a9946aab611dd2200c01ff122f64b033dad2 ]
+
+mchp_tc_probe() reads the devicetree "reg" cell - a u32, per the API
+contract of of_property_read_u32_index() - into a signed int, so the
+bounds check "channel > 2" fails to reject cell values at or above
+0x80000000: reinterpreted as a negative int, they compare below 2 and
+pass validation.
+
+A malformed devicetree can therefore drive a negative channel into the
+ATMEL_TC_REG() offset arithmetic, making the driver access syscon
+regmap offsets outside the TC block's register window, and into the
+"t%d_clk" clock-name formatting, where it truncates clk_name (sized
+for "t0_clk".."t2_clk").
+
+Declare channel as u32, matching the API contract; the unsigned
+comparison then rejects everything except channels 0..2. Adjust the
+format specifier to %u accordingly, which also resolves the W=1
+warning that exposed the gap:
+
+  microchip-tcb-capture.c:520:56: warning: '%d' directive output may
+    be truncated writing between 1 and 11 bytes into a region of size
+    6 [-Wformat-truncation=]
+  note: directive argument in the range [-2147483648, 2]
+
+No behavior change for well-formed devicetrees: channels 0..2 take
+identical paths before and after.
+
+Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
+Assisted-by: Claude:claude-fable-5 [gcc W=1]
+Signed-off-by: Babanpreet Singh <bbnpreetsingh@gmail.com>
+Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
+Link: https://lore.kernel.org/r/20260714042910.7-1-bbnpreetsingh@gmail.com
+Signed-off-by: William Breathitt Gray <wbg@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/microchip-tcb-capture.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
+index 19d457ae4c3bb..e53a8390756b7 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -483,7 +483,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+       char clk_name[7];
+       struct regmap *regmap;
+       struct clk *clk[3];
+-      int channel;
++      u32 channel;
+       int ret, i;
+       counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
+@@ -517,7 +517,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
+               priv->channel[i] = channel;
+-              snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
++              snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
+               clk[i] = of_clk_get_by_name(np->parent, clk_name);
+               if (IS_ERR(clk[i])) {
+-- 
+2.53.0
+
diff --git a/queue-7.1/devlink-fix-net-namespace-reference-leak-in-reload.patch b/queue-7.1/devlink-fix-net-namespace-reference-leak-in-reload.patch
new file mode 100644 (file)
index 0000000..065824d
--- /dev/null
@@ -0,0 +1,42 @@
+From 3b56739cb890e2403f7c51cc9fe8522723f23d12 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:06:00 +0300
+Subject: devlink: fix net namespace reference leak in reload
+
+From: Or Har-Toov <ohartoov@nvidia.com>
+
+[ Upstream commit 1c4dac9bf1d2ac31da63b794bdec697777cbd0fd ]
+
+devlink_nl_reload_doit() calls devlink_netns_get(), which returns a net
+with a held reference. When the requested namespace differs from the
+current one and the reload action is not DRIVER_REINIT, the function
+returns -EOPNOTSUPP without releasing the reference. Add the missing
+put_net() on this error path.
+
+Fixes: 2edd92570441 ("devlink: don't allow to change net namespace for FW_ACTIVATE reload action")
+Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260729080600.2427721-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/dev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/devlink/dev.c b/net/devlink/dev.c
+index 57b2b8f035436..fd5633fa88ecd 100644
+--- a/net/devlink/dev.c
++++ b/net/devlink/dev.c
+@@ -578,6 +578,7 @@ int devlink_nl_reload_doit(struct sk_buff *skb, struct genl_info *info)
+                   action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Changing namespace is only supported for reinit action");
++                      put_net(dest_net);
+                       return -EOPNOTSUPP;
+               }
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch b/queue-7.1/drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
new file mode 100644 (file)
index 0000000..de27baa
--- /dev/null
@@ -0,0 +1,79 @@
+From 0fee183f09573f4cc7ee0766e506ae38a1fee70e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:38:06 +0800
+Subject: drm/bridge: ps8640: propagate AUX transfer register errors
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 20697ecb299cd77b4cf8b28f655e56606b0472d8 ]
+
+ps8640_aux_transfer_msg() programs the AUX address registers, starts the
+AUX transfer, waits for SWAUX_SEND to clear, and reads the AUX status
+register. Several of those regmap operations have return values, but the
+function only checks a stale ret after the status read.
+
+Propagate failures from the address write, transfer start, completion
+poll, and status read. This avoids returning a transfer length when the
+bridge register transaction or AUX completion wait failed.
+
+Fixes: 13afcdd7277e ("drm/bridge: parade-ps8640: Add support for AUX channel")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patch.msgid.link/20260723103509.2-ps8640-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/parade-ps8640.c | 27 ++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
+index 825777a5758f6..db8e5889dc7f1 100644
+--- a/drivers/gpu/drm/bridge/parade-ps8640.c
++++ b/drivers/gpu/drm/bridge/parade-ps8640.c
+@@ -257,8 +257,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+       addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD :
+                                             ((len - 1) & SWAUX_LENGTH_MASK);
+-      regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
+-                        ARRAY_SIZE(addr_len));
++      ret = regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
++                              ARRAY_SIZE(addr_len));
++      if (ret) {
++              DRM_DEV_ERROR(dev,
++                            "failed to write AUX address %#x, len %zu: %d\n",
++                            msg->address, len, ret);
++              return ret;
++      }
+       if (len && (request == DP_AUX_NATIVE_WRITE ||
+                   request == DP_AUX_I2C_WRITE)) {
+@@ -274,13 +280,22 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
+               }
+       }
+-      regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      ret = regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to start AUX transfer: %d\n", ret);
++              return ret;
++      }
+       /* Zero delay loop because i2c transactions are slow already */
+-      regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
+-                               !(data & SWAUX_SEND), 0, 50 * 1000);
++      ret = regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
++                                     !(data & SWAUX_SEND), 0, 50 * 1000);
++      if (ret) {
++              DRM_DEV_ERROR(dev, "failed to complete AUX transfer: %d\n",
++                            ret);
++              return ret;
++      }
+-      regmap_read(map, PAGE0_SWAUX_STATUS, &data);
++      ret = regmap_read(map, PAGE0_SWAUX_STATUS, &data);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n",
+                             ret);
+-- 
+2.53.0
+
diff --git a/queue-7.1/drm-xe-fix-memory-leak-in-exec_queue_set_hang_replay.patch b/queue-7.1/drm-xe-fix-memory-leak-in-exec_queue_set_hang_replay.patch
new file mode 100644 (file)
index 0000000..df4e591
--- /dev/null
@@ -0,0 +1,48 @@
+From 008c255d9804831110a18e6915fdd0450d17bf91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 13:14:20 +0200
+Subject: drm/xe: Fix memory leak in exec_queue_set_hang_replay_state()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michał Winiarski <michal.winiarski@intel.com>
+
+[ Upstream commit c5f500161709f27719701334190dff2325868ef0 ]
+
+The q->replay_state is blindly overwritten, which can potentially leak
+memory that was previously allocated by vmemdup_user().
+Return an error if q->replay_state is not empty.
+
+Discovered using AI-assisted static analysis confirmed by Intel Product
+Security.
+
+Reported-by: Martin Hodo <martin.hodo@intel.com>
+Fixes: 1026c1a73a96 ("drm/xe: Implement DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE")
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patch.msgid.link/20260624111421.1258364-1-michal.winiarski@intel.com
+Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
+(cherry picked from commit f6b6cc1118bdbc4265fa8b3bdf8565b26f13e56e)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_exec_queue.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
+index 071b8c41df43e..85778958f5803 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue.c
++++ b/drivers/gpu/drm/xe/xe_exec_queue.c
+@@ -801,6 +801,9 @@ static int exec_queue_set_hang_replay_state(struct xe_device *xe,
+       u64 __user *address = u64_to_user_ptr(value);
+       void *ptr;
++      if (q->replay_state)
++              return -EINVAL;
++
+       ptr = vmemdup_user(address, size);
+       if (XE_IOCTL_DBG(xe, IS_ERR(ptr)))
+               return PTR_ERR(ptr);
+-- 
+2.53.0
+
diff --git a/queue-7.1/drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch b/queue-7.1/drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch
new file mode 100644 (file)
index 0000000..59ec40a
--- /dev/null
@@ -0,0 +1,63 @@
+From c16111e40bf11f32380c81c3d1068b0dd224e48c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jul 2026 09:59:45 +0200
+Subject: drm/xe/uc: Apply RCS/CCS yield policy to SR-IOV VFs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
+
+[ Upstream commit d1643db3b037b57f2af7f85c3821d6fe69c492f6 ]
+
+VFs were missing the call to apply the global scheduling policy.
+Call xe_guc_submit_enable() during vf_uc_load_hw() to ensure VFs
+get the same policy enforcement as PF.
+
+Fixes: 26caeae9fb48 ("drm/xe/guc: Set RCS/CCS yield policy")
+Suggested-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
+Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Link: https://patch.msgid.link/20260709075945.1337660-1-marcin.bernatowicz@linux.intel.com
+Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
+(cherry picked from commit f09360e857130f7ab7f069e2421e6b4a6e502531)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_uc.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
+index 75091bde0d50c..65f59f06177fd 100644
+--- a/drivers/gpu/drm/xe/xe_uc.c
++++ b/drivers/gpu/drm/xe/xe_uc.c
+@@ -15,6 +15,7 @@
+ #include "xe_guc_pc.h"
+ #include "xe_guc_rc.h"
+ #include "xe_guc_engine_activity.h"
++#include "xe_guc_submit.h"
+ #include "xe_huc.h"
+ #include "xe_sriov.h"
+ #include "xe_wopcm.h"
+@@ -159,12 +160,14 @@ static int vf_uc_load_hw(struct xe_uc *uc)
+       if (err)
+               return err;
+-      uc->guc.submission_state.enabled = true;
+-
+       err = xe_guc_opt_in_features_enable(&uc->guc);
+       if (err)
+               return err;
++      err = xe_guc_submit_enable(&uc->guc);
++      if (err)
++              return err;
++
+       err = xe_gt_record_default_lrcs(uc_to_gt(uc));
+       if (err)
+               return err;
+-- 
+2.53.0
+
diff --git a/queue-7.1/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch b/queue-7.1/enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch
new file mode 100644 (file)
index 0000000..cc03a02
--- /dev/null
@@ -0,0 +1,49 @@
+From 8073aba65d4ec447580482577f606c62c327bb3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 23:26:30 -0700
+Subject: enic: fix tx_hang_reset use-after-free on device removal
+
+From: Satish Kharat <satishkh@cisco.com>
+
+[ Upstream commit ec680ea4ba1bca92a767fb7e7869758bfdd886e3 ]
+
+enic_remove() cancels the reset and change_mtu_work items but does not
+cancel tx_hang_reset. A TX timeout that fires while the device is being
+removed can schedule enic_tx_hang_reset() so that it runs after
+free_netdev(), resulting in a use-after-free.
+
+cancel_work_sync() alone is not sufficient here: the still-live watchdog
+and notify paths can re-schedule these work items in the window between
+the cancel and unregister_netdev(). Use disable_work_sync(), which
+cancels the work and blocks any subsequent schedule_work() from
+requeuing it, and apply it to the reset and change_mtu_work items as
+well so the same requeue race is closed for all teardown work.
+
+Fixes: 937317c7c109 ("enic: do hang reset only in case of tx timeout")
+Signed-off-by: Satish Kharat <satishkh@cisco.com>
+Link: https://patch.msgid.link/20260728062730.2394873-1-satishkh@cisco.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/cisco/enic/enic_main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
+index e7125b8180879..d98f7e7ccab9b 100644
+--- a/drivers/net/ethernet/cisco/enic/enic_main.c
++++ b/drivers/net/ethernet/cisco/enic/enic_main.c
+@@ -3011,8 +3011,9 @@ static void enic_remove(struct pci_dev *pdev)
+       if (netdev) {
+               struct enic *enic = netdev_priv(netdev);
+-              cancel_work_sync(&enic->reset);
+-              cancel_work_sync(&enic->change_mtu_work);
++              disable_work_sync(&enic->reset);
++              disable_work_sync(&enic->tx_hang_reset);
++              disable_work_sync(&enic->change_mtu_work);
+               unregister_netdev(netdev);
+               enic_dev_deinit(enic);
+               vnic_dev_close(enic->vdev);
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-ads7828-fix-external-vref-regulator-handling.patch b/queue-7.1/hwmon-ads7828-fix-external-vref-regulator-handling.patch
new file mode 100644 (file)
index 0000000..f47dcf8
--- /dev/null
@@ -0,0 +1,71 @@
+From 8c9958524684c89821eb179c37be4d4fcb30a45e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 14:16:45 +0800
+Subject: hwmon: (ads7828) Fix external VREF regulator handling
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit fddb5ceaf901b050ed2a1a7deeecbf97e003435a ]
+
+The driver currently has two issues with the external VREF regulator
+handling in ads7828_probe():
+
+1. All errors from devm_regulator_get_optional() are ignored, causing the
+   driver to incorrectly fall back to internal VREF even for transient
+   errors like -EPROBE_DEFER or genuine failures like -ENOMEM.
+
+2. The external regulator is never enabled. The driver calls
+   regulator_get_voltage() without first calling regulator_enable(),
+   so the VREF pin may remain unpowered if the regulator is not
+   configured as always-on.
+
+Fix both issues by switching to devm_regulator_get_enable_read_voltage(),
+which handles regulator get, enable, and voltage read in one call.
+Only -ENODEV (no regulator specified in device tree) should trigger the
+fallback to internal VREF. All other errors are propagated to the caller.
+
+Fixes: a8ddfea09566 ("hwmon: (ads7828) Accept optional parameters from device tree")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260805061645.1331652-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ads7828.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
+index 149cfcec78dcc..f8f2f621dfeaf 100644
+--- a/drivers/hwmon/ads7828.c
++++ b/drivers/hwmon/ads7828.c
+@@ -106,12 +106,11 @@ static int ads7828_probe(struct i2c_client *client)
+       struct ads7828_data *data;
+       struct device *hwmon_dev;
+       unsigned int vref_mv = ADS7828_INT_VREF_MV;
+-      unsigned int vref_uv;
++      int vref_uv;
+       bool diff_input = false;
+       bool ext_vref = false;
+       unsigned int regval;
+       enum ads7828_chips chip;
+-      struct regulator *reg;
+       data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
+       if (!data)
+@@ -125,9 +124,11 @@ static int ads7828_probe(struct i2c_client *client)
+       } else if (dev->of_node) {
+               diff_input = of_property_read_bool(dev->of_node,
+                                                  "ti,differential-input");
+-              reg = devm_regulator_get_optional(dev, "vref");
+-              if (!IS_ERR(reg)) {
+-                      vref_uv = regulator_get_voltage(reg);
++              vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref");
++              if (vref_uv < 0) {
++                      if (vref_uv != -ENODEV)
++                              return vref_uv;
++              } else {
+                       vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
+                       if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
+                           vref_mv > ADS7828_EXT_VREF_MV_MAX)
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch b/queue-7.1/hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
new file mode 100644 (file)
index 0000000..379a612
--- /dev/null
@@ -0,0 +1,50 @@
+From 6a0da1d266bd488945ea7838ee5e32f5f34a9fe1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 07:19:20 +0000
+Subject: hwmon: (corsair-psu) fix possible out-of-bounds access on missing
+ string termination
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit 36c4d73ce05d1d8896c2669eb0730d35a02a2ec1 ]
+
+In theory it could be possible that the REPLY_SIZE sized buffers for
+holding the vendor and product strings could be end up missing the null
+termination (for example by malicious hardware built on purpose)
+required by the seq_printf() call. That limits the debugfs printf calls
+to a maximum string length of REPLY_SIZE.
+
+Fixes: d115b51e0e567 ("hwmon: add Corsair PSU HID controller driver")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/anLj9gPWRoRDbQBV@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index ce958cdaef58a..3c01ae3fc4af2 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -701,7 +701,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->vendor);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
+       return 0;
+ }
+@@ -711,7 +711,7 @@ static int product_show(struct seq_file *seqf, void *unused)
+ {
+       struct corsairpsu_data *priv = seqf->private;
+-      seq_printf(seqf, "%s\n", priv->product);
++      seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-corsair-psu-serialize-debugfs-access-against-h.patch b/queue-7.1/hwmon-corsair-psu-serialize-debugfs-access-against-h.patch
new file mode 100644 (file)
index 0000000..81b449f
--- /dev/null
@@ -0,0 +1,71 @@
+From 3c8acb662062397d0076ba27c2a1d697dc426736 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:21:39 +0000
+Subject: hwmon: (corsair-psu) serialize debugfs access against hwmon
+
+From: Ali Ahmet Memis <ali@iusegentoo.com>
+
+[ Upstream commit 2da6050809d437a805e7a3aa22398a15073b0234 ]
+
+corsairpsu_request() sends a rail select command and then the actual
+read as two separate transfers, both going through the single shared
+cmd_buffer and wait_completion in corsairpsu_usb_cmd(). The hwmon core
+serializes its own callers, but the debugfs files call
+corsairpsu_get_value() directly and never take that lock, so a debugfs
+read can land between another reader's rail select and its value read.
+
+The result is a value from the wrong rail reported as the right one,
+because corsairpsu_usb_cmd() only checks the command echo and both
+transfers echo the command it expects. It can also make a caller consume
+the reply meant for the other one, since raw_event() writes into the
+shared buffer and completes whoever happens to be waiting.
+
+Locking was dropped in commit 4207069edbf0 ("hwmon: (corsair-psu) Rely
+on subsystem locking") on the grounds that the subsystem serializes for
+us, which holds for sysfs but not for these files. Take
+the same lock in the debugfs paths that issue commands, using the guard
+added in commit d1e720c7328e ("hwmon: Support guard() and scoped_guard
+for subsystem locks").
+
+The lock cannot go into corsairpsu_request() itself: the hwmon core
+already holds it across ->read, so every sysfs read would deadlock.
+vendor_show() and product_show() only print strings cached during probe
+and issue no command, and corsairpsu_get_criticals() and
+corsairpsu_check_cmd_support() run before either interface is
+registered, so none of them need it.
+
+Fixes: 4207069edbf0 ("hwmon: (corsair-psu) Rely on subsystem locking")
+Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com>
+Tested-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/20260806142139.168611-1-ali@iusegentoo.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/corsair-psu.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 3c01ae3fc4af2..ebcaddf337d80 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -664,6 +664,8 @@ static void print_uptime(struct seq_file *seqf, u8 cmd)
+       long val;
+       int ret;
++      guard(hwmon_lock)(priv->hwmon_dev);
++
+       ret = corsairpsu_get_value(priv, cmd, 0, &val);
+       if (ret < 0) {
+               seq_puts(seqf, "N/A\n");
+@@ -723,6 +725,8 @@ static int ocpmode_show(struct seq_file *seqf, void *unused)
+       long val;
+       int ret;
++      guard(hwmon_lock)(priv->hwmon_dev);
++
+       /*
+        * The rail mode is switchable on the fly. The RAW interface can be used for this. But it
+        * will not be included here, because I consider it somewhat dangerous for the health of the
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch b/queue-7.1/hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch
new file mode 100644 (file)
index 0000000..7712d49
--- /dev/null
@@ -0,0 +1,105 @@
+From 45bab68cd045244b4315e082cc3391f2e00e3bb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:42:42 -0700
+Subject: hwmon: (ltc4282) Avoid overflow in maximum power calculation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit edd11a94335747423569500a194c6eaa915f2963 ]
+
+During device initialization in ltc4282_set_max_limits(), the calculation
+of the maximum power limit can suffer from a 32-bit integer overflow.
+
+static int ltc4282_set_max_limits(struct ltc4282_state *st)
+{
+    ...
+    st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI,
+                                      st->rsense) * st->vfs_out;
+    ...
+}
+
+The result of DIV_ROUND_CLOSEST() evaluates to a 32-bit unsigned integer
+on 32-bit architectures. This result is then multiplied by st->vfs_out,
+which is a 16-bit unsigned integer. According to C promotion rules, since
+both operands are 32-bit or smaller, the multiplication is performed in
+32-bit precision.
+
+If the device is configured with a low sense resistor value via the device
+tree (for example, 100 nano-ohms, resulting in st->rsense = 1) and the
+voltage is high, the division result can reach 343,750,000 and st->vfs_out
+can be 33,280. The product of these values is approximately 11.44 trillion,
+which exceeds the maximum capacity of a 32-bit integer and overflows
+before being stored in st->power_max.
+
+This overflow causes a truncated value to be assigned to st->power_max and
+written to the hardware limit register. An incorrect maximum power limit
+can trigger spurious power-bad faults or alarms, which may lead to the
+shutdown of the monitored power rail.
+
+Avoid the problem by calculating and storing the maximum power using 64-bit
+variables.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index bdbf370233d71..9ccad99f42e7f 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -138,7 +138,7 @@ struct ltc4282_state {
+        */
+       struct ltc4282_cache in0_1_cache[LTC4282_CHAN_VGPIO];
+       u32 vsense_max;
+-      long power_max;
++      s64 power_max;
+       u32 rsense;
+       u16 vdd;
+       u16 vfs_out;
+@@ -614,13 +614,12 @@ static int ltc4282_read(struct device *dev, enum hwmon_sensor_types type,
+ }
+ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
+-                                  long val)
++                                  s64 val)
+ {
+       u32 power;
+       u64 temp;
+-      if (val > st->power_max)
+-              val = st->power_max;
++      val = clamp(val, 0, st->power_max);
+       temp = val * int_pow(U8_MAX, 2) * st->rsense;
+       power = DIV64_U64_ROUND_CLOSEST(temp,
+@@ -630,7 +629,7 @@ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
+ }
+ static int ltc4282_write_power_word(const struct ltc4282_state *st, u32 reg,
+-                                  long val)
++                                  u64 val)
+ {
+       u64 temp = int_pow(U16_MAX, 2) * st->rsense, temp_2;
+       __be16 __raw;
+@@ -1223,7 +1222,8 @@ static int ltc4282_set_max_limits(struct ltc4282_state *st)
+               return ret;
+       /* Power is given by ISENSE * Vout. */
+-      st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI, st->rsense) * st->vfs_out;
++      st->power_max = DIV_ROUND_CLOSEST_ULL((u64)st->vsense_max * DECA * MILLI,
++                                            st->rsense) * st->vfs_out;
+       ret = ltc4282_write_power_byte(st, LTC4282_POWER_MAX, st->power_max);
+       if (ret)
+               return ret;
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-ltc4282-clamp-negative-current-limits.patch b/queue-7.1/hwmon-ltc4282-clamp-negative-current-limits.patch
new file mode 100644 (file)
index 0000000..de4d1c6
--- /dev/null
@@ -0,0 +1,69 @@
+From 408cdd6a05775fb38cdb009b69641c8867c24498 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 16:26:05 -0700
+Subject: hwmon: (ltc4282) Clamp negative current limits
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit e253dd5f9f6d875a317895bf43ec9534ed7523cb ]
+
+When a negative value is passed to ltc4282_write_curr(), the signed long
+val is cast directly to u64:
+
+drivers/hwmon/ltc4282.c:ltc4282_write_curr() {
+        /* need to pass it in millivolt */
+        u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
+        ...
+}
+
+This cast converts negative inputs into large positive values. The
+subsequent division result overflows the u32 in variable, truncating
+to a pseudo-random positive value. When this is passed to
+ltc4282_write_voltage_byte(), it is clamped to the maximum limit instead
+of zero.
+
+Clamp val to 0 and to the maximum supported upper limit before the cast
+and assign the result to a 64-bit temporary variable before the division
+to avoid the underflow and an also possible overflow.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index 9ccad99f42e7f..9c88e98e101e2 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -14,6 +14,7 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/math.h>
++#include <linux/math64.h>
+ #include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/mod_devicetable.h>
+@@ -930,8 +931,11 @@ static int ltc4282_curr_reset_hist(struct ltc4282_state *st)
+ static int ltc4282_write_curr(struct ltc4282_state *st, u32 attr,
+                             long val)
+ {
++      s32 ulimit = min_t(u64, INT_MAX,
++                         div_u64((u64)INT_MAX * DECA * MICRO, st->rsense));
++      u64 val64 = clamp(val, 0, ulimit);
+       /* need to pass it in millivolt */
+-      u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
++      u32 in = DIV_ROUND_CLOSEST_ULL(val64 * st->rsense, DECA * MICRO);
+       switch (attr) {
+       case hwmon_curr_max:
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch b/queue-7.1/hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch
new file mode 100644 (file)
index 0000000..37fc772
--- /dev/null
@@ -0,0 +1,68 @@
+From ebb36540dfed859270a95ef9bd73784b91ca7b9e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 17:30:42 -0700
+Subject: hwmon: (ltc4282) Fix parsing adi,current-limit-sense-microvolt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 335698fd7f60b6707b21fda725f97f35fa956b07 ]
+
+ltc4282_parse_dt() evaluates the wrong variable when parsing the current
+limit.
+
+When the adi,current-limit-sense-microvolt property is parsed into
+st->vsense_max, the subsequent switch statement evaluates the unrelated
+val variable instead of st->vsense_max:
+
+drivers/hwmon/ltc4282.c:ltc4282_parse_dt() {
+    ...
+        ret = device_property_read_u32(dev, "adi,current-limit-sense-microvolt",
+                                       &st->vsense_max);
+        if (!ret) {
+                int reg_val;
+
+                switch (val) {
+                case 12500:
+                        reg_val = 0;
+                        break;
+    ...
+}
+
+Because val holds a small integer representing vin_mode (from 0 to 3), it
+never matches any of the valid current limit cases.
+
+This causes it to always fall through to the default error case, return
+-EINVAL, and aborts probe initialization for any device tree using this
+property.
+
+Validate st->vsense_max instead to fix the problem.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
+Cc: Nuno Sa <nuno.sa@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc4282.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
+index 9c88e98e101e2..d7c6226081440 100644
+--- a/drivers/hwmon/ltc4282.c
++++ b/drivers/hwmon/ltc4282.c
+@@ -1395,7 +1395,7 @@ static int ltc4282_setup(struct ltc4282_state *st, struct device *dev)
+       if (!ret) {
+               int reg_val;
+-              switch (val) {
++              switch (st->vsense_max) {
+               case 12500:
+                       reg_val = 0;
+                       break;
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch b/queue-7.1/hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
new file mode 100644 (file)
index 0000000..4d1f500
--- /dev/null
@@ -0,0 +1,57 @@
+From 6d49b2cdae7eec6bd485853063f0b04c3be3e0ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:48:42 +0800
+Subject: hwmon: (nzxt-smart2) Check return value of init_device() in probe
+
+From: Qingshuang Fu <fuqingshuang@kylinos.cn>
+
+[ Upstream commit d533882ce1060866a590257f2c77ee23eabef5b8 ]
+
+The init_device() call in nzxt_smart2_hid_probe() can fail because it
+sends HID output reports to the hardware to detect fans and set the
+update interval.  If the hardware is not responding or the HID reports
+fail, init_device() returns a negative error code.
+
+However, the return value was ignored, causing the probe to continue
+and register an hwmon device even though the device was never properly
+initialized.  This leads to an inconsistent state where the driver
+reports stale data or blocks on wait queues that will never be woken.
+
+The same function's return value is already checked in the
+reset_resume() handler, confirming the author's intent that errors
+should be propagated.
+
+Note that this fix was not possible before commit 59d104b54b0b
+("hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop")
+because the out_hw_close error path was missing hid_device_io_stop(),
+which would have opened a use-after-free risk window.
+
+Fixes: 53e68c20aeb1 ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2.")
+Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
+Link: https://lore.kernel.org/r/20260804074842.505923-1-fffsqian@163.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/nzxt-smart2.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
+index ff0c0bee0e839..efc78a8f58c88 100644
+--- a/drivers/hwmon/nzxt-smart2.c
++++ b/drivers/hwmon/nzxt-smart2.c
+@@ -754,7 +754,11 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
+       hid_device_io_start(hdev);
+-      init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      ret = init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
++      if (ret) {
++              dev_err(&hdev->dev, "init_device failed: %d\n", ret);
++              goto out_hw_close;
++      }
+       drvdata->hwmon =
+               hwmon_device_register_with_info(&hdev->dev, "nzxtsmart2", drvdata,
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-pmbus-core-avoid-race-condition-during-probe.patch b/queue-7.1/hwmon-pmbus-core-avoid-race-condition-during-probe.patch
new file mode 100644 (file)
index 0000000..63504e0
--- /dev/null
@@ -0,0 +1,51 @@
+From 3a88d6a66279be50634c6680587234b77332b75b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 11:40:50 -0700
+Subject: hwmon: (pmbus/core) Avoid race condition during probe
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 71638a456852a18a4578f52d51926ba1d223053b ]
+
+pmbus_write_smbalert_mask() is not guarded, which can cause race conditions
+with concurrent sysfs attribute accesses.
+
+Similar, PMBus accesses in pmbus_init_debugfs() are not guarded, also
+resulting in potential race conditions.
+
+Add guards to both functions to prevent the races.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: 221819ca4c36e ("hwmon: (pmbus/core) Add interrupt support")
+Fixes: 1e069dfd96dfe ("hwmon: (pmbus) Add debugfs for status registers")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index 5567d37f13fe2..095e128709af4 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -3427,6 +3427,8 @@ static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg,
+ {
+       int ret;
++      guard(pmbus_lock)(client);
++
+       ret = _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
+       /*
+@@ -3662,6 +3664,8 @@ static void pmbus_init_debugfs(struct i2c_client *client,
+       if (!entries)
+               return;
++      guard(pmbus_lock)(client);
++
+       /*
+        * Add device-specific entries.
+        * Please note that the PMBUS standard allows all registers to be
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-pmbus-fix-type-confusion-in-notification-logic.patch b/queue-7.1/hwmon-pmbus-fix-type-confusion-in-notification-logic.patch
new file mode 100644 (file)
index 0000000..9e92680
--- /dev/null
@@ -0,0 +1,234 @@
+From a6a7b662b6e5bfbcc3ca78d66da230ff8e2bd035 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:57:35 -0700
+Subject: hwmon: (pmbus) Fix type confusion in notification logic
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 59bd68ab05a8f9c9a60b6ec44682084184803ff4 ]
+
+Sashiko reports:
+
+At the start of the loop in pmbus_notify(), the code unconditionally casts
+every attribute to a struct sensor_device_attribute:
+
+drivers/hwmon/pmbus/pmbus_core.c:pmbus_notify() {
+    for (i = 0; i < data->num_attributes; i++) {
+        struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
+        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+        int index = attr->index;
+...
+}
+
+However, data->group.attrs can contain other types like struct
+pmbus_samples_reg or struct pmbus_sensor, which only embed a base
+struct device_attribute.
+
+If da is a struct pmbus_samples_reg, dev_attr is the last member. Casting
+it to struct sensor_device_attribute and reading the index field appears
+to access memory past the end of the allocation, which might trigger a
+slab-out-of-bounds read.
+
+Additionally, if da is a struct pmbus_sensor, casting it causes the index
+field to overlap with the page, phase, and reg fields. Could this produce
+a garbage mask on little-endian systems that spuriously matches the target
+reg, page, and flags during an alert?
+
+Fix the problem by using struct sensor_device_attr in struct pmbus_sensor
+and struct pmbus_label. Since those attributes never trigger a
+notification, set the value of attr->index to -1 for them. Use this value
+to distinguish from boolean attributes which _can_ trigger a notification
+and use the index field to encode mask, page, and register values.
+
+Fixes: f469bde9afd1 ("hwmon: (pmbus/core) Notify hwmon events")
+Cc: Vincent Jardin <vjardin@free.fr>
+Tested-by: Vincent Jardin <vjardin@free.fr>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 61 +++++++++++++++++++-------------
+ 1 file changed, 37 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index 095e128709af4..3b219ed5386fb 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -45,7 +45,7 @@ module_param(wp, int, 0444);
+ struct pmbus_sensor {
+       struct pmbus_sensor *next;
+       char name[PMBUS_NAME_SIZE];     /* sysfs sensor name */
+-      struct device_attribute attribute;
++      struct sensor_device_attribute attribute;
+       u8 page;                /* page number */
+       u8 phase;               /* phase number, 0xff for all phases */
+       u16 reg;                /* register */
+@@ -68,7 +68,7 @@ struct pmbus_boolean {
+ struct pmbus_label {
+       char name[PMBUS_NAME_SIZE];     /* sysfs label name */
+-      struct device_attribute attribute;
++      struct sensor_device_attribute attribute;
+       char label[PMBUS_NAME_SIZE];    /* label */
+ };
+ #define to_pmbus_label(_attr) \
+@@ -1241,7 +1241,8 @@ static ssize_t pmbus_show_sensor(struct device *dev,
+                                struct device_attribute *devattr, char *buf)
+ {
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_sensor *sensor = to_pmbus_sensor(attr);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       s64 val;
+@@ -1261,7 +1262,8 @@ static ssize_t pmbus_set_sensor(struct device *dev,
+ {
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       struct pmbus_data *data = i2c_get_clientdata(client);
+-      struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_sensor *sensor = to_pmbus_sensor(attr);
+       s64 val;
+       int ret;
+       u16 regval;
+@@ -1283,7 +1285,8 @@ static ssize_t pmbus_set_sensor(struct device *dev,
+ static ssize_t pmbus_show_label(struct device *dev,
+                               struct device_attribute *da, char *buf)
+ {
+-      struct pmbus_label *label = to_pmbus_label(da);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++      struct pmbus_label *label = to_pmbus_label(attr);
+       return sysfs_emit(buf, "%s\n", label->label);
+ }
+@@ -1436,8 +1439,8 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+                                            bool update, bool readonly,
+                                            bool writeonly, bool convert)
+ {
++      struct sensor_device_attribute *a;
+       struct pmbus_sensor *sensor;
+-      struct device_attribute *a;
+       sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
+       if (!sensor)
+@@ -1461,12 +1464,11 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+       sensor->update = update;
+       sensor->convert = convert;
+       sensor->data = -ENODATA;
+-      pmbus_dev_attr_init(a, sensor->name,
+-                          readonly ? 0444 : 0644,
+-                          writeonly ? pmbus_show_zero : pmbus_show_sensor,
+-                          pmbus_set_sensor);
++      pmbus_attr_init(a, sensor->name, readonly ? 0444 : 0644,
++                      writeonly ? pmbus_show_zero : pmbus_show_sensor,
++                      pmbus_set_sensor, -1);
+-      if (pmbus_add_attribute(data, &a->attr))
++      if (pmbus_add_attribute(data, &a->dev_attr.attr))
+               return NULL;
+       sensor->next = data->sensors;
+@@ -1483,8 +1485,8 @@ static int pmbus_add_label(struct pmbus_data *data,
+                          const char *name, int seq,
+                          const char *lstring, int index, int phase)
+ {
++      struct sensor_device_attribute *a;
+       struct pmbus_label *label;
+-      struct device_attribute *a;
+       label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL);
+       if (!label)
+@@ -1508,8 +1510,8 @@ static int pmbus_add_label(struct pmbus_data *data,
+                                lstring, index, phase);
+       }
+-      pmbus_dev_attr_init(a, label->name, 0444, pmbus_show_label, NULL);
+-      return pmbus_add_attribute(data, &a->attr);
++      pmbus_attr_init(a, label->name, 0444, pmbus_show_label, NULL, -1);
++      return pmbus_add_attribute(data, &a->dev_attr.attr);
+ }
+ /*
+@@ -2397,7 +2399,7 @@ struct pmbus_samples_attr {
+ struct pmbus_samples_reg {
+       int page;
+       struct pmbus_samples_attr *attr;
+-      struct device_attribute dev_attr;
++      struct sensor_device_attribute attribute;
+ };
+ static struct pmbus_samples_attr pmbus_samples_registers[] = {
+@@ -2419,14 +2421,15 @@ static struct pmbus_samples_attr pmbus_samples_registers[] = {
+       }
+ };
+-#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, dev_attr)
++#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, attribute)
+ static ssize_t pmbus_show_samples(struct device *dev,
+                                 struct device_attribute *devattr, char *buf)
+ {
+       int val;
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_samples_reg *reg = to_samples_reg(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_samples_reg *reg = to_samples_reg(attr);
+       scoped_guard(pmbus_lock, client) {
+               val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
+@@ -2444,7 +2447,8 @@ static ssize_t pmbus_set_samples(struct device *dev,
+       int ret;
+       long val;
+       struct i2c_client *client = to_i2c_client(dev->parent);
+-      struct pmbus_samples_reg *reg = to_samples_reg(devattr);
++      struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++      struct pmbus_samples_reg *reg = to_samples_reg(attr);
+       if (kstrtol(buf, 0, &val) < 0)
+               return -EINVAL;
+@@ -2459,6 +2463,7 @@ static ssize_t pmbus_set_samples(struct device *dev,
+ static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
+                                 struct pmbus_samples_attr *attr)
+ {
++      struct sensor_device_attribute *a;
+       struct pmbus_samples_reg *reg;
+       reg = devm_kzalloc(data->dev, sizeof(*reg), GFP_KERNEL);
+@@ -2468,10 +2473,12 @@ static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
+       reg->attr = attr;
+       reg->page = page;
+-      pmbus_dev_attr_init(&reg->dev_attr, attr->name, 0644,
+-                          pmbus_show_samples, pmbus_set_samples);
++      a = &reg->attribute;
++
++      pmbus_attr_init(a, attr->name, 0644,
++                      pmbus_show_samples, pmbus_set_samples, -1);
+-      return pmbus_add_attribute(data, &reg->dev_attr.attr);
++      return pmbus_add_attribute(data, &a->dev_attr.attr);
+ }
+ static int pmbus_add_samples_attributes(struct i2c_client *client,
+@@ -2979,9 +2986,15 @@ static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
+               struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
+               struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+               int index = attr->index;
+-              u16 smask = pb_index_to_mask(index);
+-              u8 spage = pb_index_to_page(index);
+-              u16 sreg = pb_index_to_reg(index);
++              u16 smask, sreg;
++              u8 spage;
++
++              if (index == -1)
++                      continue;
++
++              smask = pb_index_to_mask(index);
++              spage = pb_index_to_page(index);
++              sreg = pb_index_to_reg(index);
+               if (reg == sreg && page == spage && (smask & flags)) {
+                       dev_dbg(data->dev, "sysfs notify: %s", da->attr.name);
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch b/queue-7.1/hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
new file mode 100644 (file)
index 0000000..1157e8e
--- /dev/null
@@ -0,0 +1,71 @@
+From 1dca2ccd6013ea578be70772580511241eadd1af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 14:12:31 -0700
+Subject: hwmon: (pmbus/lm25066) Fix PMBus coefficient calculations
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 0dabe8a56f772f0ece46d2597799f412c277d874 ]
+
+In lm25066_probe(), the PMBus coefficients for current and power are
+scaled based on the shunt resistor value. The calculation evaluates the
+multiplication using 32-bit arithmetic because info->m is an int and
+shunt is a u32:
+
+static int lm25066_probe(struct i2c_client *client) {
+    ...
+    info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+    info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
+    ...
+}
+
+For large coefficients like 26882 (LM25056) or 15076 (LM5066i), a device
+tree shunt-resistor-micro-ohms value exceeding approximately 159,000
+(159 mOhm, which is physically valid for low-current applications) causes
+the intermediate product to exceed UINT_MAX (4,294,967,295). This results
+in a silent wraparound before the division by 1000.
+
+Furthermore, if the wrapped value has the most significant bit set,
+converting it back to the signed int info->m results in negative
+coefficients. This logic error leads to drastically corrupted current and
+power readings, which can cause erratic thermal or power management
+behavior in the system.
+
+Fix the problem by using 64-bit operations for the multiply/divide
+operations. This can still overflow, but only for unreasonably large
+shunt resistor values.
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Fixes: 94ee5fcc240fe ("hwmon: (pmbus/lm25066) Support configurable sense resistor values")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/lm25066.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+index 0f7df7e2c9c5b..cb42832cebf0c 100644
+--- a/drivers/hwmon/pmbus/lm25066.c
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+ #include <linux/log2.h>
++#include <linux/math.h>
+ #include <linux/of.h>
+ #include "pmbus.h"
+@@ -540,8 +541,8 @@ static int lm25066_probe(struct i2c_client *client)
+       if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
+               shunt = 1000;
+-      info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
+-      info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
++      info->m[PSC_CURRENT_IN] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_CURRENT_IN] * shunt, 1000);
++      info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_POWER] * shunt, 1000);
+ #if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)
+       /* LM25056 doesn't support OPERATION */
+-- 
+2.53.0
+
diff --git a/queue-7.1/hwmon-support-guard-and-scoped_guard-for-subsystem-l.patch b/queue-7.1/hwmon-support-guard-and-scoped_guard-for-subsystem-l.patch
new file mode 100644 (file)
index 0000000..8761c21
--- /dev/null
@@ -0,0 +1,62 @@
+From 768cc92123fd5d3f3d58f988224b1eef0fad0c4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 07:14:33 -0700
+Subject: hwmon: Support guard() and scoped_guard for subsystem locks
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit d1e720c7328e046049b792d03fae093d4d3a72e4 ]
+
+Add support for guard() and scoped_guard() for the hwmon subsystem lock
+to simplify its use.
+
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Stable-dep-of: 2da6050809d4 ("hwmon: (corsair-psu) serialize debugfs access against hwmon")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/hwmon-kernel-api.rst | 7 ++++---
+ include/linux/hwmon.h                    | 3 +++
+ 2 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/hwmon/hwmon-kernel-api.rst b/Documentation/hwmon/hwmon-kernel-api.rst
+index 1d7f1397a8274..9fcde32a140df 100644
+--- a/Documentation/hwmon/hwmon-kernel-api.rst
++++ b/Documentation/hwmon/hwmon-kernel-api.rst
+@@ -85,9 +85,10 @@ removal.
+ When using ``[devm_]hwmon_device_register_with_info()`` to register the
+ hardware monitoring device, accesses using the associated access functions
+ are serialised by the hardware monitoring core. If a driver needs locking
+-for other functions such as interrupt handlers or for attributes which are
+-fully implemented in the driver, hwmon_lock() and hwmon_unlock() can be used
+-to ensure that calls to those functions are serialized.
++for other functions such as interrupt handlers, attributes which are fully
++implemented in the driver, or debugfs functions, hwmon_lock() and hwmon_unlock()
++can be used to ensure that calls to those functions are serialized. Those
++functions also support guard() and scoped_guard() variants.
+ Using devm_hwmon_device_register_with_info()
+ --------------------------------------------
+diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
+index 301a83afbd663..f5330e7ae247c 100644
+--- a/include/linux/hwmon.h
++++ b/include/linux/hwmon.h
+@@ -13,6 +13,7 @@
+ #define _HWMON_H_
+ #include <linux/bitops.h>
++#include <linux/cleanup.h>
+ struct device;
+ struct attribute_group;
+@@ -495,6 +496,8 @@ char *devm_hwmon_sanitize_name(struct device *dev, const char *name);
+ void hwmon_lock(struct device *dev);
+ void hwmon_unlock(struct device *dev);
++DEFINE_GUARD(hwmon_lock, struct device *, hwmon_lock(_T), hwmon_unlock(_T))
++
+ /**
+  * hwmon_is_bad_char - Is the char invalid in a hwmon name
+  * @ch: the char to be considered
+-- 
+2.53.0
+
diff --git a/queue-7.1/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch b/queue-7.1/ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
new file mode 100644 (file)
index 0000000..2942ed1
--- /dev/null
@@ -0,0 +1,259 @@
+From ec87973180f65d920783cd2ffa28310218446cf6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:05 +0300
+Subject: ipvs: avoid out-of-bounds write in ip_vs_nat_icmp
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 646922a0379496154e8c8faca4f8e2fd9100cacc ]
+
+Sashiko warns that local attacker can modify the packet
+while it is processed by IPVS. Some places read the
+IP ihl field multiple times which can cause out-of-bounds
+access. One such place is ip_vs_nat_icmp where we
+can write after the validated area.
+
+Fix it by providing ciph argument just like it is done for
+IPv6 and use ciph->len as offset to the embedded transport
+header.
+
+Modify some IPv4 header checks by reading the ihl field
+only once.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://sashiko.dev/#/patchset/20260722101517.36313-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h             |  2 +-
+ net/netfilter/ipvs/ip_vs_core.c | 67 +++++++++++++++++----------------
+ net/netfilter/ipvs/ip_vs_xmit.c |  2 +-
+ 3 files changed, 36 insertions(+), 35 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 8d98f7e0a9fb2..ebd88f58afe16 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -2040,7 +2040,7 @@ static inline bool ip_vs_conn_use_hash2(struct ip_vs_conn *cp)
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int dir, unsigned int toff,
+-                  bool has_ports);
++                  bool has_ports, struct ip_vs_iphdr *ciph);
+ #ifdef CONFIG_IP_VS_IPV6
+ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index 6b79e0c4d9e28..0bdaeb4ed61e4 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -925,28 +925,27 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
+  */
+ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                   struct ip_vs_conn *cp, int inout, unsigned int toff,
+-                  bool has_ports)
++                  bool has_ports, struct ip_vs_iphdr *ciph)
+ {
+       struct iphdr *iph        = ip_hdr(skb);
+       struct icmphdr *icmph    = (struct icmphdr *)(skb->data + toff);
+-      struct iphdr *ciph       = (struct iphdr *)(icmph + 1);
+-      unsigned int coff __maybe_unused = toff + sizeof(struct icmphdr);
++      struct iphdr *cih        = (struct iphdr *)(icmph + 1);
+       if (inout) {
+               iph->saddr = cp->vaddr.ip;
+               ip_send_check(iph);
+-              ciph->daddr = cp->vaddr.ip;
+-              ip_send_check(ciph);
++              cih->daddr = cp->vaddr.ip;
++              ip_send_check(cih);
+       } else {
+               iph->daddr = cp->daddr.ip;
+               ip_send_check(iph);
+-              ciph->saddr = cp->daddr.ip;
+-              ip_send_check(ciph);
++              cih->saddr = cp->daddr.ip;
++              ip_send_check(cih);
+       }
+       /* the TCP/UDP/SCTP port */
+       if (has_ports) {
+-              __be16 *ports = (void *)ciph + ciph->ihl*4;
++              __be16 *ports = (void *)(skb->data + ciph->len);
+               if (inout)
+                       ports[1] = cp->vport;
+@@ -960,10 +959,10 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       if (inout)
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered outgoing ICMP");
+       else
+-              IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
++              IP_VS_DBG_PKT(11, AF_INET, pp, skb, ciph->off,
+                             "Forwarding altered incoming ICMP");
+ }
+@@ -1056,7 +1055,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
+               ip_vs_nat_icmp_v6(skb, pp, cp, 1, toff, has_ports, ciph);
+       else
+ #endif
+-              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports);
++              ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports, ciph);
+       if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
+               goto out;
+@@ -1092,7 +1091,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       struct ip_vs_iphdr ciph;
+       struct ip_vs_conn *cp;
+       struct ip_vs_protocol *pp;
+-      unsigned int offset, ihl;
++      unsigned int offset;
+       union nf_inet_addr snet;
+       *related = 1;
+@@ -1105,7 +1104,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+                       return NF_ACCEPT;
+       }
+-      ihl = ipvsh->len;
+       offset = ipvsh->len;
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
+@@ -1131,11 +1129,15 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      pp = ip_vs_proto_get(cih->protocol);
++      pp = ip_vs_proto_get(ciph.protocol);
+       if (!pp)
+               return NF_ACCEPT;
+@@ -1146,8 +1148,6 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking outgoing ICMP for");
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order */
+       cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
+                            ipvs, AF_INET, skb, &ciph);
+@@ -1155,8 +1155,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
+               return NF_ACCEPT;
+       snet.ip = ipvsh->saddr.ip;
+-      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph, ihl,
+-                                  hooknum);
++      return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph,
++                                  ipvsh->len, hooknum);
+ }
+ #ifdef CONFIG_IP_VS_IPV6
+@@ -1803,10 +1803,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       /* Now find the contained IP header */
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-      if (!(cih && cih->version == 4 && cih->ihl >= 5))
++      if (!cih)
+               return NF_ACCEPT; /* The packet looks wrong, ignore */
+-      raddr = (union nf_inet_addr *)&cih->daddr;
+       hlen_ipip = cih->ihl * 4;
++      if (!(cih->version == 4 && hlen_ipip >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++      raddr = (union nf_inet_addr *)&cih->daddr;
+       /* Special case for errors for IPIP/UDP/GRE tunnel packets */
+       tunnel = false;
+@@ -1823,9 +1825,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+               if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP)
+                       return NF_ACCEPT;
+               offset += hlen_ipip;
+-              cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+-              if (!(cih && cih->version == 4 && cih->ihl >= 5))
+-                      return NF_ACCEPT; /* The packet looks wrong, ignore */
+               tunnel = true;
+       } else if ((cih->protocol == IPPROTO_UDP ||     /* Can be UDP encap */
+                   cih->protocol == IPPROTO_GRE) &&    /* Can be GRE encap */
+@@ -1850,21 +1849,25 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+                       /* Skip IP and UDP/GRE tunnel headers */
+                       offset = offset2 + ulen;
+                       /* Now we should be at the original IP header */
+-                      cih = skb_header_pointer(skb, offset, sizeof(_ciph),
+-                                               &_ciph);
+-                      if (cih && cih->version == 4 && cih->ihl >= 5 &&
+-                          iproto == IPPROTO_IPIP)
++                      if (iproto == IPPROTO_IPIP)
+                               tunnel = true;
+                       else
+                               return NF_ACCEPT;
+               }
+       }
+-      pd = ip_vs_proto_data_get(ipvs, cih->protocol);
++      if (!ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph))
++              return NF_ACCEPT;
++      pd = ip_vs_proto_data_get(ipvs, ciph.protocol);
+       if (!pd)
+               return NF_ACCEPT;
+       pp = pd->pp;
++      cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
++      if (!(cih && cih->version == 4 &&
++            ciph.len - ciph.off >= sizeof(struct iphdr)))
++              return NF_ACCEPT; /* The packet looks wrong, ignore */
++
+       /* Is the embedded protocol header present? */
+       if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
+               return NF_ACCEPT;
+@@ -1872,9 +1875,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+                     "Checking incoming ICMP for");
+-      offset2 = offset;
+-      ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph);
+-
+       /* The embedded headers contain source and dest in reverse order.
+        * For IPIP/UDP/GRE tunnel this is error for request, not for reply.
+        */
+@@ -1904,11 +1904,12 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
+       }
+       if (tunnel) {
+-              unsigned int hlen_orig = cih->ihl * 4;
++              unsigned int hlen_orig = ciph.len - ciph.off;
+               __be32 info = ic->un.gateway;
+               __u8 type = ic->type;
+               __u8 code = ic->code;
++              offset2 = offset;
+               /* Update the MTU */
+               if (ic->type == ICMP_DEST_UNREACH &&
+                   ic->code == ICMP_FRAG_NEEDED) {
+diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
+index 0b0c5304993a9..c4508f3f43dd3 100644
+--- a/net/netfilter/ipvs/ip_vs_xmit.c
++++ b/net/netfilter/ipvs/ip_vs_xmit.c
+@@ -1580,7 +1580,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+       if (skb_cow(skb, rt->dst.dev->hard_header_len))
+               goto tx_error;
+-      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports);
++      ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports, ciph);
+       /* Another hack: avoid icmp_send in ip_fragment */
+       skb->ignore_df = 1;
+-- 
+2.53.0
+
diff --git a/queue-7.1/ipvs-return-the-csum-validation-for-forward-hook.patch b/queue-7.1/ipvs-return-the-csum-validation-for-forward-hook.patch
new file mode 100644 (file)
index 0000000..1c97bd5
--- /dev/null
@@ -0,0 +1,100 @@
+From 3ba9ebe662d19910af31d6872e54516f1b223609 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 21:35:06 +0300
+Subject: ipvs: return the csum validation for forward hook
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 99609cb0aa789c8d071050ce8579989551882cc6 ]
+
+Sashiko notes that playing games with the skb dst and rt
+flags instead of providing hooknum is not a good idea
+when validating the checksums.
+
+Also, skipping checksum validation for FORWARD packets
+risk silent data corruption, even if the only user is
+the FTP-CMD packets coming from the real server.
+
+Sashiko also noticed that by using common checksum
+helper in the previous commit we actually fixed old bug
+where the TCP/UDP checksum for IPv6 on CHECKSUM_COMPLETE
+was not validated correctly.
+
+Fixes: e876b75b9020 ("ipvs: fix the checksum validations")
+Link: https://sashiko.dev/#/patchset/20260722211420.153933-1-pablo%40netfilter.org
+Link: https://sashiko.dev/#/patchset/20260727185024.67534-1-ja%40ssi.bg
+Link: https://sashiko.dev/#/patchset/20260728202520.59179-1-ja%40ssi.bg
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/ip_vs.h                   | 19 +++++--------------
+ net/netfilter/ipvs/ip_vs_proto_sctp.c |  2 +-
+ 2 files changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index ebd88f58afe16..ac82e6af55ec6 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -25,9 +25,7 @@
+ #include <linux/netfilter.h>          /* for union nf_inet_addr */
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>                       /* for struct ipv6hdr */
+-#include <net/route.h>
+ #include <net/ipv6.h>
+-#include <net/ip6_fib.h>
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ #include <net/netfilter/nf_conntrack.h>
+ #endif
+@@ -2073,30 +2071,23 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
+       return csum_partial(diff, sizeof(diff), oldsum);
+ }
+-static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
++static inline bool ip_vs_checksum_needed(struct sk_buff *skb)
+ {
+       /* Checksum unnecessary or already validated? */
+       if (skb_csum_unnecessary(skb))
+               return false;
+-      /* LOCAL_OUT ? */
+-      if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
++      /* Locally generated ? */
++      if (!skb->dev)
+               return false;
+-      /* !LOCAL_IN (FORWARD) ? */
+-      if (af == AF_INET6) {
+-              if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
+-                      return false;
+-      } else {
+-              if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+-                      return false;
+-      }
+       return true;
+ }
+ static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
+                                              int offset, int proto, int af)
+ {
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return true;
++      /* Validate csum even for FORWARD */
+       return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+index 3dbd3096e1637..c80567c73469b 100644
+--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+@@ -193,7 +193,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+       struct sctphdr *sh;
+       __le32 cmp, val;
+-      if (!ip_vs_checksum_needed(skb, af))
++      if (!ip_vs_checksum_needed(skb))
+               return 1;
+       sh = (struct sctphdr *)(skb->data + sctphoff);
+       cmp = sh->checksum;
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch b/queue-7.1/net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
new file mode 100644 (file)
index 0000000..5488736
--- /dev/null
@@ -0,0 +1,81 @@
+From 049a92d550a4238c596a4ed1aabf7373bb04aa4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 13:15:08 +0000
+Subject: net/atm: fix slab-out-of-bounds read in vcc_setsockopt()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d0c80dbb970439bd2eeb0e5effff8c16a5f4e1e3 ]
+
+vcc_setsockopt() contained an ineffective optlen check:
+  if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+      return -EINVAL;
+
+If __SO_LEVEL_MATCH(optname, level) evaluated to false (e.g. if the caller
+passed a mismatched level), the length check optlen != __SO_SIZE(optname)
+was short-circuited and bypassed. Execution then fell through to switch(optname),
+calling copy_from_sockptr() assuming optval contained sufficient space.
+
+Furthermore, even if level matched, a cgroup BPF setsockopt filter could shrink
+optlen after entry. Because copy_from_sockptr() on kernel pointers uses memcpy(),
+this leads to a KASAN slab-out-of-bounds read when optlen is smaller than the
+expected structure size.
+
+Fix this by using copy_safe_from_sockptr(), which unconditionally validates
+that optlen is at least the expected size before copying. Also change the local
+'value' variable type from 'unsigned long' to 'int' so that SO_SETCLP matches
+its sizeof(int) ABI encoding on 64-bit systems.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+53ecc09fb81df10ef4de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=53ecc09fb81df10ef4de
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260805131508.3227331-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/atm/common.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/net/atm/common.c b/net/atm/common.c
+index 6eb78c34c2843..c3fbbb63c5d89 100644
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+                  sockptr_t optval, unsigned int optlen)
+ {
+       struct atm_vcc *vcc;
+-      unsigned long value;
++      int value;
+       int error;
+       if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
+@@ -772,8 +772,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+       {
+               struct atm_qos qos;
+-              if (copy_from_sockptr(&qos, optval, sizeof(qos)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&qos, sizeof(qos), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               error = check_qos(&qos);
+               if (error)
+                       return error;
+@@ -786,8 +788,10 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
+               return 0;
+       }
+       case SO_SETCLP:
+-              if (copy_from_sockptr(&value, optval, sizeof(value)))
+-                      return -EFAULT;
++              error = copy_safe_from_sockptr(&value, sizeof(value), optval,
++                                             optlen);
++              if (error)
++                      return error;
+               if (value)
+                       vcc->atm_options |= ATM_ATMOPT_CLP;
+               else
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch b/queue-7.1/net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
new file mode 100644 (file)
index 0000000..7f5639c
--- /dev/null
@@ -0,0 +1,42 @@
+From aa3622d8e3550cb1d0ca6b9290569c19e5accdf0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 12:17:10 +0400
+Subject: net: hisilicon: hix5hd2_gmac: remove redundant NAPI delete
+
+From: Jiawen Liu <1298662399@qq.com>
+
+[ Upstream commit f307a7dc32097c11413178fca437a10d20890bc2 ]
+
+hix5hd2_dev_remove() calls netif_napi_del() before unregister_netdev().
+This is not needed because free_netdev() deletes all NAPI instances
+attached to the net_device.
+
+Remove the redundant call and let the networking core tear down the NAPI
+instance during unregister_netdev(). The probe error path still keeps its
+explicit netif_napi_del(), because the device has not been registered
+there.
+
+Fixes: 57c5bc9ad7d7 ("net: hisilicon: add hix5hd2 mac driver")
+Signed-off-by: Jiawen Liu <1298662399@qq.com>
+Link: https://patch.msgid.link/tencent_5FFD37A252B4FEA6A80AD25B17C8E904F005@qq.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+index e3e7f2270560c..02282dc86faf4 100644
+--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+@@ -1282,7 +1282,6 @@ static void hix5hd2_dev_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct hix5hd2_priv *priv = netdev_priv(ndev);
+-      netif_napi_del(&priv->napi);
+       unregister_netdev(ndev);
+       mdiobus_unregister(priv->bus);
+       mdiobus_free(priv->bus);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-hns3-fix-speed-configuration-residue-after-drive.patch b/queue-7.1/net-hns3-fix-speed-configuration-residue-after-drive.patch
new file mode 100644 (file)
index 0000000..a86ee55
--- /dev/null
@@ -0,0 +1,76 @@
+From 13138e0e7ccc96a785d45716599e0baabf7ea920 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 17:30:36 +0800
+Subject: net: hns3: fix speed configuration residue after driver reload
+
+From: Jijie Shao <shaojijie@huawei.com>
+
+[ Upstream commit 3860d8748af315bfee6fe669fddc1fc17d3214db ]
+
+After setting a 100G optical port to 40G via ethtool and reloading
+the driver, the port remains at 40G instead of reverting to the
+firmware default speed of 100G.
+
+The commit referenced in Fixes: added two overwrites in
+hclge_init_ae_dev() for non-copper media, so that optical ports
+connected to forced-mode remotes inherit the firmware-preset
+autoneg and speed instead of the hardcoded defaults:
+
+  req_autoneg = mac.autoneg
+  req_speed   = mac.speed         (when autoneg disabled)
+
+The autoneg overwrite keeps existing behavior:
+hclge_set_autoneg_speed_dup() already uses mac.autoneg (not
+req_autoneg) since it was introduced, so autoneg inheritance from
+firmware was already in place. This part is kept.
+
+The speed overwrite, however, introduces the residue: mac.speed
+reflects whatever was last programmed into the MAC, and after unload
+firmware does not restore the MAC speed to the flash default. So if
+the user changed speed via ethtool in a prior load, mac.speed still
+carries that value on reload and req_speed inherits it.
+
+Fix by dropping the req_speed overwrite only. req_speed keeps the
+firmware default value set in hclge_configure() (cfg.default_speed),
+so a reload reverts the speed to default, matching the expectation
+that a driver reload resets link configuration.
+
+Trade-off: on optical ports whose firmware default speed does not
+match a forced-mode remote, reload now drops the link and the user
+must re-apply ethtool configuration. This is acceptable: a driver
+reload is expected to reset link configuration, not to inherit
+runtime state from before unload. The autoneg inheritance is left
+in place as established behavior; changing it is out of scope for
+this patch and would itself be a user-perceivable behavior change.
+
+Fixes: d9d349c4e8a0 ("net: hns3: differentiate autoneg default values between copper and fiber")
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260724093036.426631-1-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 2a6e4d17452c4..13c20a8ca3b0f 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -11926,12 +11926,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+       if (ret)
+               goto err_ptp_uninit;
+-      if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER) {
++      if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER)
+               hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg;
+-              if (hdev->hw.mac.autoneg == AUTONEG_DISABLE &&
+-                  hdev->hw.mac.speed != SPEED_UNKNOWN)
+-                      hdev->hw.mac.req_speed = hdev->hw.mac.speed;
+-      }
+       ret = hclge_set_autoneg_speed_dup(hdev);
+       if (ret) {
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-mlx5-fw_tracer-return-null-on-create-error.patch b/queue-7.1/net-mlx5-fw_tracer-return-null-on-create-error.patch
new file mode 100644 (file)
index 0000000..91942ae
--- /dev/null
@@ -0,0 +1,134 @@
+From 30e50e8a071d0e7283008fafb6f87a9b841fdbc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 11:04:02 +0300
+Subject: net/mlx5: fw_tracer, return NULL on create error
+
+From: Michael Guralnik <michaelgur@nvidia.com>
+
+[ Upstream commit af39eb111ce6b5eba9c08513b62c4868eb7e7fd5 ]
+
+Tracer creation can fail by returning either NULL or ERR_PTR.
+The return value is stored without a check on the device, and users
+treat ERR_PTR and NULL the same way.
+This also causes a crash in the core dump logic, which is missing the
+ERR_PTR check and ends up dereferencing it, as shown in the trace below.
+
+Switch tracer creation to return NULL on failure only, so callers only
+need a single NULL check.
+
+  Internal error: Oops: 0000000096000006 [#1]  SMP
+  Modules linked in: mlx5_ib ib_uverbs ib_core ipv6 mlx5_core
+  CPU: 1 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.19.7 #1 PREEMPT(none)
+  Workqueue: mlx5_health0001:01:00.0 mlx5_fw_reporter_err_work [mlx5_core]
+  pstate: a3400009 (NzCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+  pc : mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core]
+  lr : mlx5_fw_tracer_trigger_core_dump_general+0x40/0xe0 [mlx5_core]
+  sp : ffff800081cf3c40
+  x29: ffff800081cf3c90 x28: 0000000000000000 x27: 0000000000000000
+  x26: ffff000080018828 x25: 0000000000000000 x24: ffff000080304a05
+  x23: ffff800081cf3d80 x22: ffff0000847e01a0 x21: 0000000000000000
+  x20: ffff0000847e01a0 x19: ffffffffffffffa1 x18: ffff80008310bbf0
+  x17: ffff800080119650 x16: ffff80008010df54 x15: ffff80008010d4ac
+  x14: ffff800079c202e4 x13: ffff80008002fe60 x12: ffff800080119650
+  x11: ffff80008010df54 x10: ffff80008010d4ac x9 : ffff800079c203d8
+  x8 : ffff800081cf3c88 x7 : 0000000000000000 x6 : 0000000000000000
+  x5 : 0000000000000000 x4 : 0000000000000008 x3 : 0000000000000030
+  x2 : 0000000000000008 x1 : 0000000000000000 x0 : 00000000c5c4000e
+  Call trace:
+   mlx5_fw_tracer_trigger_core_dump_general+0x58/0xe0 [mlx5_core] (P)
+   mlx5_fw_reporter_dump+0x30/0x2e0 [mlx5_core]
+   devlink_health_do_dump+0x9c/0x160
+   devlink_health_report+0x1c0/0x288
+   mlx5_fw_reporter_err_work+0xac/0xc0 [mlx5_core]
+   process_one_work+0x15c/0x3d8
+   worker_thread+0x18c/0x320
+   kthread+0x148/0x228
+   ret_from_fork+0x10/0x20
+  Code: b9400000 5ac00800 7a401800 540003ca (3940a260)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x000000,00078031,75fce5a1,35fffe67
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception ]---
+
+Fixes: fd1483fe1f9f ("net/mlx5: Add support for FW reporter dump")
+Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260729080402.2427184-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 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 adcc73e2a5b38..1493d8106c1a4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+@@ -1025,13 +1025,11 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       tracer = kvzalloc_obj(*tracer);
+       if (!tracer)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
+       tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
+-      if (!tracer->work_queue) {
+-              err = -ENOMEM;
++      if (!tracer->work_queue)
+               goto free_tracer;
+-      }
+       tracer->dev = dev;
+@@ -1073,7 +1071,7 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
+       destroy_workqueue(tracer->work_queue);
+ free_tracer:
+       kvfree(tracer);
+-      return ERR_PTR(err);
++      return NULL;
+ }
+ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);
+@@ -1084,7 +1082,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       if (!tracer->str_db.loaded)
+@@ -1134,7 +1132,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
+ /* Stop tracer + Cleanup HW resources */
+ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mutex_lock(&tracer->state_lock);
+@@ -1163,7 +1161,7 @@ void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
+ /* Free software resources (Buffers, etc ..) */
+ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
+ {
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return;
+       mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");
+@@ -1215,7 +1213,7 @@ int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
+       struct mlx5_core_dev *dev;
+       int err;
+-      if (IS_ERR_OR_NULL(tracer))
++      if (!tracer)
+               return 0;
+       dev = tracer->dev;
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-mlx5e-fix-bql-reset-on-sq-re-activation.patch b/queue-7.1/net-mlx5e-fix-bql-reset-on-sq-re-activation.patch
new file mode 100644 (file)
index 0000000..dad9247
--- /dev/null
@@ -0,0 +1,58 @@
+From ecccff705f2c3e7808414aefe779e6b5b20db02b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 16:47:29 -0700
+Subject: net/mlx5e: fix BQL reset on SQ re-activation
+
+From: Bobby Eshleman <bobbyeshleman@meta.com>
+
+[ Upstream commit e7386770be1bf810bcd6af39d1e4bfeab3408430 ]
+
+mlx5e_queue_start() deactivates and re-activates all channels but closes
+only the queue being restarted. mlx5e_activate_txqsq() then
+unconditionally calls netdev_tx_reset_queue(), zeroing the BQL counters
+of channels that kept their in-flight TX WQEs. The next completion then
+over-charges and trips the BUG_ON() in dql_completed():
+
+  kernel BUG at lib/dynamic_queue_limits.c:99!
+  RIP: 0010:dql_completed+0x23d/0x280
+  Call Trace:
+   <IRQ>
+   mlx5e_poll_tx_cq+0x668/0xa60
+   mlx5e_napi_poll+0x5b/0x7b0
+   net_rx_action+0x15a/0x580
+
+Reset BQL only when the SQ has no bytes in flight (sq->cc == sq->pc).
+
+In the case that reset is skipped, the outstanding WQEs will eventually
+complete and rebalance the dql. The dql->limit is carried across the
+reset.
+
+Fixes: b2588ea40ec9 ("net/mlx5e: Implement queue mgmt ops and single channel swap")
+Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260803-mlx5-bql-v3-1-a30d4c66fe1d@meta.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 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 7d1063c7bf649..22ae49af38cd7 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -1939,8 +1939,10 @@ int mlx5e_open_txqsq(struct mlx5e_channel *c, u32 tisn, int txq_ix,
+ void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
+ {
+       sq->txq = netdev_get_tx_queue(sq->netdev, sq->txq_ix);
++      /* Reset BQL only when the SQ has no bytes in flight. */
++      if (sq->cc == sq->pc)
++              netdev_tx_reset_queue(sq->txq);
+       set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
+-      netdev_tx_reset_queue(sq->txq);
+       netif_tx_start_queue(sq->txq);
+       netif_queue_set_napi(sq->netdev, sq->txq_ix, NETDEV_QUEUE_TYPE_TX, sq->cq.napi);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch b/queue-7.1/net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
new file mode 100644 (file)
index 0000000..d8ad8bd
--- /dev/null
@@ -0,0 +1,100 @@
+From 169d11155baa196ab37a3cf65cd959be90365c7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 07:43:38 +0300
+Subject: net/mlx5e: TC, Check if flow is PEER before acquiring devcom lock
+
+From: Shay Drory <shayd@nvidia.com>
+
+[ Upstream commit 6ddfba2ea98db21b001e0e5c472499156224650c ]
+
+In case __mlx5e_add_fdb_flow() fails in lower levels, the flow is
+deleted via mlx5e_tc_del_flow(), and mlx5e_tc_del_flow() is acquiring
+ESW devcom lock without condition. In addition, in case of peer_flow,
+__mlx5e_add_fdb_flow() is called while holding ESW devcom comp lock.
+This results in an AA deadlock.
+
+To fix this, introduce a new PEER flag that is set on flows created as
+peer flows (the duplicate flows on peer devices), and check it in
+mlx5e_tc_del_flow() before acquiring ESW devcom lock.
+
+Lockdep splat:
+============================================
+WARNING: possible recursive locking detected
+============================================
+ Possible unsafe locking scenario:
+       CPU0
+       ----
+  lock(&comp->lock_key#2);
+  lock(&comp->lock_key#2);
+ *** DEADLOCK ***
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x69/0xa0
+ print_deadlock_bug.cold+0xbd/0xca
+ __lock_acquire+0x1671/0x2ec0
+ lock_acquire+0x10e/0x2e0
+ down_read+0x95/0x430
+ mlx5_devcom_for_each_peer_begin+0x4e/0xe0 [mlx5_core]
+ mlx5e_tc_del_flow+0x11d/0xa70 [mlx5_core]
+ mlx5e_flow_put+0x99/0x100 [mlx5_core]
+ __mlx5e_add_fdb_flow+0x409/0xf00 [mlx5_core]
+ mlx5e_configure_flower+0x2a86/0x4100 [mlx5_core]
+ mlx5e_rep_setup_tc_cls_flower+0x12f/0x1b0 [mlx5_core]
+ mlx5e_rep_setup_tc_cb+0x153/0x750 [mlx5_core]
+ tc_setup_cb_add+0x1dc/0x470
+ fl_change+0x2f4d/0x626d [cls_flower]
+ tc_new_tfilter+0x79b/0x2310
+ rtnetlink_rcv_msg+0x778/0xad0
+ do_syscall_64+0x70/0x960
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ </TASK>
+
+Fixes: 04de7dda7394 ("net/mlx5e: Infrastructure for duplicated offloading of TC flows")
+Signed-off-by: Shay Drory <shayd@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260728044338.2271143-1-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h | 1 +
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c      | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+index efb34de4cb7ad..692ac2f21d94e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+@@ -30,6 +30,7 @@ enum {
+       MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 9,
+       MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 10,
+       MLX5E_TC_FLOW_FLAG_USE_ACT_STATS         = MLX5E_TC_FLOW_BASE + 11,
++      MLX5E_TC_FLOW_FLAG_PEER                  = MLX5E_TC_FLOW_BASE + 12,
+ };
+ struct mlx5e_tc_flow_parse_attr {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 8b5a421a22a37..f3d4586e09e37 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -2165,7 +2165,8 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
+       if (mlx5e_is_eswitch_flow(flow)) {
+               struct mlx5_devcom_comp_dev *devcom = flow->priv->mdev->priv.eswitch->devcom;
+-              if (!mlx5_devcom_for_each_peer_begin(devcom)) {
++              if (flow_flag_test(flow, PEER) ||
++                  !mlx5_devcom_for_each_peer_begin(devcom)) {
+                       mlx5e_tc_del_fdb_flow(priv, flow);
+                       return;
+               }
+@@ -4605,6 +4606,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
+       else
+               in_mdev = priv->mdev;
++      flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_PEER);
+       parse_attr = flow->attr->parse_attr;
+       peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
+                                        parse_attr->filter_dev,
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch b/queue-7.1/net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
new file mode 100644 (file)
index 0000000..f6d27d3
--- /dev/null
@@ -0,0 +1,60 @@
+From 9749bd46332b48554dead722d8c087cff5d127c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 12:36:18 +0800
+Subject: net/ncsi: fix heap OOB read in NCSI_CMD_SEND_CMD payload length
+
+From: Henry Martin <bsdhenrymartin@gmail.com>
+
+[ Upstream commit afa58b7384913c8773d837acdb07b035690ec5d2 ]
+
+ncsi_send_cmd_nl() takes the number of bytes to copy from the
+attacker-controlled ncsi_pkt_hdr.length field of the in-band packet
+header, while the source buffer is the NCSI_ATTR_DATA netlink
+attribute whose readable size is nla_len() - sizeof(ncsi_pkt_hdr).
+The two length sources are never cross-checked: only
+nla_len() >= sizeof(struct ncsi_pkt_hdr) is enforced.
+
+With hdr->length set larger than the attribute payload (up to 65535
+against at most 2032 readable bytes), ncsi_cmd_handler_oem() copies
+past the end of the netlink attribute buffer with unsafe_memcpy(),
+leaking up to ~64KB of kernel heap memory into the transmitted NCSI
+command packet. The destination skb is sized by the declared payload,
+so the write side does not overflow - this is a pure OOB read /
+information leak, reachable with CAP_NET_ADMIN on systems with a
+registered NCSI device (e.g. OpenBMC on Aspeed BMC SoCs, where
+NET_NCSI=y is standard).
+
+Reject commands whose declared payload extends past the end of the
+data attribute.
+
+The issue was found by the autokbug dynamic kernel fuzzer at Tencent
+Yunding Lab.
+
+Fixes: 9771b8ccdfa6 ("net/ncsi: Extend NC-SI Netlink interface to allow user space to send NC-SI command")
+Reported-by: Henry Martin <bsdhenrymartin@gmail.com>
+Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
+Link: https://patch.msgid.link/20260803043618.3210301-1-bsdhenrymartin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ncsi/ncsi-netlink.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index 2f872d064396d..8cc538358f6a3 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -461,6 +461,10 @@ static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
+       nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
+       nca.info = info;
+       nca.payload = ntohs(hdr->length);
++      if (nca.payload > len - sizeof(*hdr)) {
++              ret = -EINVAL;
++              goto out_netlink;
++      }
+       nca.data = data + sizeof(*hdr);
+       ret = ncsi_xmit_cmd(&nca);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-openvswitch-check-ethernet-header-length-in-key_.patch b/queue-7.1/net-openvswitch-check-ethernet-header-length-in-key_.patch
new file mode 100644 (file)
index 0000000..6ec715c
--- /dev/null
@@ -0,0 +1,78 @@
+From ec5380945f2ebfe6b5877cd547217640449a3228 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 18:20:06 -0400
+Subject: net/openvswitch: check Ethernet header length in key_extract()
+
+From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+
+[ Upstream commit cf6f8b29befb92173659bcef6a441d274947bfae ]
+
+When a packet arrives on an ARPHRD_NONE device (e.g. TUN),
+ovs_flow_key_extract() trusts the user-provided skb->protocol field: if
+it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and
+key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes
+of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes
+for MAC addresses and parse_ethertype() pulls 2 more, either of which
+triggers a kernel BUG in __skb_pull() when the linear area is too small.
+
+  kernel BUG at include/linux/skbuff.h:2848!
+  RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933
+  ovs_flow_key_extract+0x419/0xa70
+  ovs_vport_receive+0x222/0x390
+  netdev_frame_hook+0x3e0/0x630
+  tun_get_user+0x2d0c/0x38e0
+
+Fixed by calling check_header() in key_extract() before accessing the
+Ethernet header.
+
+Fixes: 217ac77a3c25 ("openvswitch: allow L3 netdev ports")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
+Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Link: https://patch.msgid.link/20260730222006.118652-1-blbllhy@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/flow.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 66366982f6044..46c1d66aad8c3 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -889,8 +889,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  * Ethernet header
+  * @key: output flow key
+  *
+- * The caller must ensure that skb->len >= ETH_HLEN.
+- *
+  * Initializes @skb header fields as follows:
+  *
+  *    - skb->mac_header: the L2 header.
+@@ -910,8 +908,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+  */
+ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ {
+-      struct ethhdr *eth;
+-
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+@@ -926,6 +922,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
++              struct ethhdr *eth;
++              int err;
++
++              err = check_header(skb, ETH_HLEN);
++              if (unlikely(err))
++                      return err;
++
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-prestera-validate-firmware-header-length.patch b/queue-7.1/net-prestera-validate-firmware-header-length.patch
new file mode 100644 (file)
index 0000000..3bcc68e
--- /dev/null
@@ -0,0 +1,42 @@
+From 4960ebb48afafc02410597756b261d6526305133 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 22:19:06 +0800
+Subject: net: prestera: validate firmware header length
+
+From: Pengpeng Hou <pengpeng@iscas.ac.cn>
+
+[ Upstream commit 8ae344eb540af3f457179b52bc6061416752485c ]
+
+prestera_fw_hdr_parse() reads the firmware header before checking
+that the firmware image contains that header.
+
+Reject images shorter than struct prestera_fw_header before decoding the
+magic and version fields.
+
+Fixes: 4c2703dfd7fabb ("net: marvell: prestera: Add PCI interface support")
+Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
+Acked-by: Elad Nachman <enachman@marvell.com>
+Link: https://patch.msgid.link/20260731141500.1-prestera-v2-pengpeng@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/prestera/prestera_pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+index 2989a77e3b422..1ad0e62a8433b 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+@@ -684,6 +684,9 @@ static int prestera_fw_hdr_parse(struct prestera_fw *fw)
+       struct prestera_fw_header *hdr;
+       u32 magic;
++      if (fw->bin->size < sizeof(*hdr))
++              return -EINVAL;
++
+       hdr = (struct prestera_fw_header *)fw->bin->data;
+       magic = be32_to_cpu(hdr->magic_number);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-qrtr-ns-raise-lookup-limit-to-128.patch b/queue-7.1/net-qrtr-ns-raise-lookup-limit-to-128.patch
new file mode 100644 (file)
index 0000000..36afd44
--- /dev/null
@@ -0,0 +1,51 @@
+From 1eded2c917d84ec894633ae4e06fe12542acfa6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 22:18:30 +0200
+Subject: net: qrtr: ns: Raise lookup limit to 128
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Łukasz Patron <priv.luk@gmail.com>
+
+[ Upstream commit 7fc1c937b6b37c77df4ba374c37435ab06a2e945 ]
+
+Current limit of 64 is not enough for Sony Xperia 10 VII (SM6475).
+
+After merging v6.6.142 into a downstream AOSP device, it's stuck on
+boot animation and following log spam can be observed in dmesg:
+
+E qrtr    : ctrl_cmd_new_lookup(): QRTR client node exceeds max lookup limit!
+E qrtr    : qrtr_ns_worker(): failed while handling packet from 1:16600
+
+No idea why it needs more than 64 client lookups, but it appears to
+work fine with 128 as it did when there were no limits.
+
+I don't really have a good way to investigate what it needs all
+these lookups for as most of the userspace is closed source.
+
+Fixes: 5640227d9a21 ("net: qrtr: ns: Limit the maximum number of lookups")
+Signed-off-by: Łukasz Patron <priv.luk@gmail.com>
+Link: https://patch.msgid.link/20260804201919.1148015-1-priv.luk@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/qrtr/ns.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
+index e5b2adb161d92..c5e7e01db2498 100644
+--- a/net/qrtr/ns.c
++++ b/net/qrtr/ns.c
+@@ -78,7 +78,7 @@ struct qrtr_node {
+  */
+ #define QRTR_NS_MAX_NODES   512
+ #define QRTR_NS_MAX_SERVERS 256
+-#define QRTR_NS_MAX_LOOKUPS 64
++#define QRTR_NS_MAX_LOOKUPS 128
+ static u16 node_count;
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-remove-warn_on_once-from-sk_mc_loop.patch b/queue-7.1/net-remove-warn_on_once-from-sk_mc_loop.patch
new file mode 100644 (file)
index 0000000..5c364e7
--- /dev/null
@@ -0,0 +1,45 @@
+From 8d03a9d59e6587f199494059edf3527c1ecb4281 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 15:20:48 +0000
+Subject: net: remove WARN_ON_ONCE() from sk_mc_loop()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b8a39a09ae4eaae04309e1e38ed6a1101d967496 ]
+
+sk_mc_loop() can be called for sockets that are neither AF_INET
+nor AF_INET6 (e.g. AF_PACKET sockets when sending packets via raw/packet
+socket over virtual devices such as VRF or ipvlan).
+
+In such cases, sk_family is not AF_INET/AF_INET6 and sk_mc_loop() falls
+through the switch statement and triggers WARN_ON_ONCE(1).
+
+Non-INET sockets do not support IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP
+options, so loopback should default to true without generating a warning.
+
+Fixes: f60e5990d9c1 ("ipv6: protect skb->sk accesses from recursive dereference inside the stack")
+Reported-by: syzbot+22c3218a6fa219e47321@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a72024c.13623e66.bdc14.0019.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260804152048.2134341-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 5714436b08710..aaa3bb214eff9 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -779,7 +779,6 @@ bool sk_mc_loop(const struct sock *sk)
+               return inet6_test_bit(MC6_LOOP, sk);
+ #endif
+       }
+-      WARN_ON_ONCE(1);
+       return true;
+ }
+ EXPORT_SYMBOL(sk_mc_loop);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch b/queue-7.1/net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
new file mode 100644 (file)
index 0000000..7cab59c
--- /dev/null
@@ -0,0 +1,116 @@
+From ee943a757bb754d3eec26d4d2ebe32773b706415 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Aug 2026 08:56:32 -0400
+Subject: net/sched: cls_api: Always acquire rtnl_lock when destroying locked
+ classifiers
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit a347304b2ca1a5377d5bd2d8a72e4b4f12afe648 ]
+
+Another challenge with unlocked filters.
+There is a short window in tc_new_tfilter where a tcf_proto can be found
+and briefly referenced by a totally unrelated, unlocked classifier's request
+and cause a race.
+
+Feng created a poc which created this race with two threads, one creating a
+u32 filter and other a flower filter in the same chain/prio:
+
+1. Both threads enter tc_new_tfilter, both find the chain empty, both
+   drop filter_chain_lock
+2. u32 finishes tcf_proto_create("u32") first, calls
+   tcf_chain_tp_insert_unique() -> inserts u32_tp into the chain
+3. flower finishes tcf_proto_create("flower") later, calls
+   tcf_chain_tp_insert_unique() -> tcf_chain_tp_find() now sees u32_tp
+   already there, takes a reference on it, destroys flower's own tp_new
+   and returns u32_tp to the caller.
+
+Flower then hits the kind mismatch check (because it requested for kind
+"flower" but tp->ops->kind is "u32") and goes through the errout path
+which calls tcf_proto_put() on u32_tp. If the u32 thread has already
+gone through its own errout (its change() call failed on the PoC's empty
+options) and dropped its create and insert refs, flower's put is the
+last one and drops u32_tp's refcnt to zero.
+
+At this point tp->ops->destroy() runs in a context that never took
+rtnl_lock. When that happens, it might cause a UAF like the following
+(illustrated by the PoC):
+
+[  +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
+[  +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524
+
+  Call Trace:
+   u32_init (net/sched/cls_u32.c:393)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Allocated by task 526:
+   u32_init (net/sched/cls_u32.c:378)
+   tc_new_tfilter (net/sched/cls_api.c:2378)
+
+  Freed by task 522:
+   kfree
+   u32_destroy (net/sched/cls_u32.c:662)
+   tcf_proto_destroy (net/sched/cls_api.c:446)
+   tcf_proto_put (net/sched/cls_api.c:459)
+   tc_new_tfilter (net/sched/cls_api.c:2459)
+
+Fix this by having tcf_proto_destroy() take rtnl_lock around
+tp->ops->destroy() for locked classifiers whenever rtnl is not held.
+
+To explain why I used a temp variable "not_lockless" I'd like to point to a
+semi-related note on rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (adding here
+for future cleanup if deemed necessary):
+The rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are
+redundant sources of truth for whether rtnl_lock is held. Among the nine
+classifier destroy(..rtnl_held..) callbacks, only flower consults the
+rtnl_held parameter which it propagates to tc_setup_cb_destroy()
+and tc_setup_cb_call(). The other eight (u32, flow, bpf, cgroup, route, basic,
+fw, mall) ignore it entirely;-> those that call tc_setup_cb_destroy()
+(u32, bpf, mall) hardcode true always instead of forwarding the parameter.
+
+A future cleanup should remove the rtnl_held parameter from the destroy callback
+signature entirely and have callers rely solely on their knowledge whether
+they are running in an unlocked context.
+
+Fixes: 12db03b65c2b ("net: sched: extend proto ops to support unlocked classifiers")
+Reported-by: Feng Xue <feng.xue@outlook.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260801125632.360365-1-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_api.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index fee4524adc98e..4e6a2812a4f32 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -443,7 +443,22 @@ static void tcf_chain_put(struct tcf_chain *chain);
+ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
+                             bool sig_destroy, struct netlink_ext_ack *extack)
+ {
+-      tp->ops->destroy(tp, rtnl_held, extack);
++      /* A locked classifier's destroy callback (e.g. u32_destroy) uses
++       * rtnl_dereference() and mutates shared structures (e.g. the
++       * tc_u_common hash list) that are only safe under rtnl_lock. When an
++       * unlocked classifier's request (e.g. flower on ingress) loses the
++       * tcf_chain_tp_insert_unique() race and ends up dropping the last
++       * reference on a locked classifier's proto, destroy() would run
++       * without rtnl held. Take it here in that case.
++       */
++      bool not_lockless = !rtnl_held &&
++              !(tp->ops->flags & TCF_PROTO_OPS_DOIT_UNLOCKED);
++
++      if (not_lockless)
++              rtnl_lock();
++      tp->ops->destroy(tp, rtnl_held || not_lockless, extack);
++      if (not_lockless)
++              rtnl_unlock();
+       tcf_proto_count_usesw(tp, false);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch b/queue-7.1/net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
new file mode 100644 (file)
index 0000000..8026fae
--- /dev/null
@@ -0,0 +1,142 @@
+From 2259bde902cae4fac469ed19b559baf2e6509bf4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 05:44:11 -0400
+Subject: net/sched: cls_route: fix fastmap use-after-free on filter
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 47d7f7051253bdc02b1d245d87e38f16d31a74df ]
+
+The route4 classifier maintains a 16-slot fastmap cache that stores raw
+struct route4_filter pointers indexed by (id, iif). The reader
+(route4_classify) populates this cache via route4_set_fastmap() for every
+classified packet that hits a filter. The writer (route4_delete,
+route4_change) clears the cache via route4_reset_fastmap() before
+RCU-deferred kfree of the filter.
+
+This creates a UAF race:
+ 1. Reader walks the RCU-protected bucket chain, finds filter f
+ 2. Writer unlinks f, calls route4_reset_fastmap(), then tcf_queue_work()
+ 3. Reader calls route4_set_fastmap() and writes f into the cache
+    *after* the writer's reset, caching a pointer about to be freed
+ 4. After the RCU grace period, kfree(f) executes
+ 5. Next classified packet on the same (id, iif) tuple hits the stale
+    fastmap entry and reads f->res from freed memory
+
+Reproduced with an mdelay(100) accelerator in route4_set_fastmap() and a
+concurrent add/delete stress test (provided by both zdi and Santosh).
+Both triggered KASAN slab-use-after-free reports in the route4 fastmap
+paths.
+
+Fix:
+Introduce a per-filter boolean dying flag to suppress stale fastmap
+republishing by in-flight readers.
+
+Fixes: 1109c00547fc ("net: sched: RCU cls_route")
+Reported-by: zdi-disclosures@trendmicro.com
+Reported-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Santosh Kalluri <santosh.kalluri129@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260729094411.46257-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_route.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
+index bd6f945bd3883..eded7aacd3f70 100644
+--- a/net/sched/cls_route.c
++++ b/net/sched/cls_route.c
+@@ -52,6 +52,7 @@ struct route4_filter {
+       struct tcf_result       res;
+       struct tcf_exts         exts;
+       u32                     handle;
++      bool                    dying;
+       struct route4_bucket    *bkt;
+       struct tcf_proto        *tp;
+       struct rcu_work         rwork;
+@@ -66,9 +67,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
+ static DEFINE_SPINLOCK(fastmap_lock);
+ static void
+-route4_reset_fastmap(struct route4_head *head)
++route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
+ {
+       spin_lock_bh(&fastmap_lock);
++      if (f)
++              f->dying = true;
+       memset(head->fastmap, 0, sizeof(head->fastmap));
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -81,9 +84,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
+       /* fastmap updates must look atomic to aling id, iff, filter */
+       spin_lock_bh(&fastmap_lock);
+-      head->fastmap[h].id = id;
+-      head->fastmap[h].iif = iif;
+-      head->fastmap[h].filter = f;
++      if (f == ROUTE4_FAILURE || !f->dying) {
++              head->fastmap[h].id = id;
++              head->fastmap[h].iif = iif;
++              head->fastmap[h].filter = f;
++      }
+       spin_unlock_bh(&fastmap_lock);
+ }
+@@ -297,6 +302,13 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                                       next = rtnl_dereference(f->next);
+                                       RCU_INIT_POINTER(b->ht[h2], next);
+                                       tcf_unbind_filter(tp, &f->res);
++                                      /* Mark the filter dying under fastmap_lock so
++                                       * any in-flight reader that still holds it
++                                       * will skip the republish in route4_set_fastmap().
++                                       */
++                                      spin_lock_bh(&fastmap_lock);
++                                      f->dying = true;
++                                      spin_unlock_bh(&fastmap_lock);
+                                       if (tcf_exts_get_net(&f->exts))
+                                               route4_queue_work(f);
+                                       else
+@@ -307,6 +319,11 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
+                       kfree_rcu(b, rcu);
+               }
+       }
++
++      /* All filters are unlinked and marked dying, so no in-flight
++       * reader can republish a stale entry after this reset.
++       */
++      route4_reset_fastmap(head, NULL);
+       kfree_rcu(head, rcu);
+ }
+@@ -334,11 +351,11 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
+                       /* unlink it */
+                       RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+-                      /* Remove any fastmap lookups that might ref filter
+-                       * notice we unlink'd the filter so we can't get it
+-                       * back in the fastmap.
++                      /* Clear any fastmap entries that may ref this filter and
++                       * mark it dying so in-flight readers can't republish it
++                       * after the reset.
+                        */
+-                      route4_reset_fastmap(head);
++                      route4_reset_fastmap(head, f);
+                       /* Delete it */
+                       tcf_unbind_filter(tp, &f->res);
+@@ -558,7 +575,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
+               }
+       }
+-      route4_reset_fastmap(head);
++      route4_reset_fastmap(head, fold);
+       *arg = f;
+       if (fold) {
+               tcf_unbind_filter(tp, &fold->res);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch b/queue-7.1/net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
new file mode 100644 (file)
index 0000000..b9a6c81
--- /dev/null
@@ -0,0 +1,50 @@
+From aef9fc0afb86114783e6f60c76c7330ea59b6ec3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 21:14:16 +0200
+Subject: net/sched: sch_cake: drop WARN_ON(1) for malformed packets in ACK
+ filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@toke.dk>
+
+[ Upstream commit 2a33516f9ef59ad11844d4fc152f889449b5daf3 ]
+
+The sch_cake ACK filter parses packets to find the TCP header and filter
+duplicated ACKs if the flow is backlogged. The parsing code contains a
+WARN_ON(1) which can be triggered by a malformed IP header in certain
+cases. Depending on the system configuration, this leads either to
+either spamming dmesg with warnings, or a panic if panic_on_warn is set.
+
+The code already correctly skips the offending packet in the branch that
+triggers the warning, so the WARN_ON itself doesn't really serve any
+purpose. So just drop it altogether to avoid the inconvenient side
+effects.
+
+Fixes: 8b7138814f29 ("sch_cake: Add optional ACK filter")
+Reported-by: Zhiling Zou <zhilinz@nebusec.ai>
+Reported-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20260729191417.45665-1-toke@toke.dk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_cake.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
+index 8965fe252471c..755c42c32bcf3 100644
+--- a/net/sched/sch_cake.c
++++ b/net/sched/sch_cake.c
+@@ -1287,7 +1287,6 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
+                       seglen = ipv6_payload_len(skb, ipv6h_check);
+               } else {
+-                      WARN_ON(1);  /* shouldn't happen */
+                       continue;
+               }
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch b/queue-7.1/net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
new file mode 100644 (file)
index 0000000..c7589a9
--- /dev/null
@@ -0,0 +1,57 @@
+From a24c997bfac0ab87cf2fb25c57c2a6a350619482 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:01:53 +0200
+Subject: net/smc: fix qentry overwrite for CONFIRM_LINK and ADD_LINK_CONT in
+ smc_llc_event_handler()
+
+From: Mahanta Jambigi <mjambigi@linux.ibm.com>
+
+[ Upstream commit 976245094925bab9bc39366b2e9ab44ffcde61d0 ]
+
+The SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT branch in
+smc_llc_event_handler() stores an incoming qentry into the local LLC flow
+without first checking whether a qentry is already pending. If a malicious or
+buggy peer sends a second CONFIRM_LINK or ADD_LINK_CONT request while a flow is
+active and flow->qentry is already set, smc_llc_flow_qentry_set() overwrites the
+pointer without freeing the previous allocation, leaking one kmalloc-96 object
+per spurious message.
+
+The sibling SMC_LLC_DELETE_LINK branch already has the correct !flow->qentry
+guard. Apply the same guard to the CONFIRM_LINK/ADD_LINK_CONT branch so that a
+duplicate message when qentry is already occupied falls through to break and is
+freed by the kfree(qentry) at the out: label, rather than silently leaking the
+existing allocation.
+
+The response direction (smc_llc_rx_response()) is unaffected: it already guards
+with flow->qentry at the equivalent site and drops duplicate responses
+correctly.
+
+Fixes: 0fb0b02bd6fd ("net/smc: adapt SMC client code to use the LLC flow")
+Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260729130153.970800-1-mjambigi@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_llc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
+index 954b2ff1815c2..aa6d83af55eda 100644
+--- a/net/smc/smc_llc.c
++++ b/net/smc/smc_llc.c
+@@ -1927,7 +1927,8 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
+               return;
+       case SMC_LLC_CONFIRM_LINK:
+       case SMC_LLC_ADD_LINK_CONT:
+-              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
++              if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE &&
++                  !lgr->llc_flow_lcl.qentry) {
+                       /* a flow is waiting for this message */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch b/queue-7.1/net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
new file mode 100644 (file)
index 0000000..c35f3f4
--- /dev/null
@@ -0,0 +1,71 @@
+From 9b5b62d248d46973973c30491047e09b4e2c4e44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 09:07:01 +0200
+Subject: net/smc: fix TOCTOU race between smc_listen_out() and listener close
+
+From: Sidraya Jayagond <sidraya@linux.ibm.com>
+
+[ Upstream commit 185a4caeecabc150106deda1da170b09f2ad803f ]
+
+smc_listen_out() reads lsmc->sk.sk_state without the listener lock,
+then acquires lock_sock_nested() only after the check passes. This
+opens a window where smc_close_active() can transition the listener
+to SMC_CLOSED, call smc_close_cleanup_listen() to drain the accept
+queue, and release the lock, all between the lockless read and the
+delayed lock acquisition:
+
+  smc_listen_work (smc_hs_wq)          smc_close_active()
+  -------------------------------      -------------------------
+  release_sock(child)
+  if (sk_state == SMC_LISTEN) TRUE
+                                        lock_sock(listener)
+                                        sk_state = SMC_CLOSED
+                                        smc_close_cleanup_listen()
+                                        release_sock(listener)
+                                        flush_work(tcp_listen_work)
+  lock_sock_nested(listener)
+  smc_accept_enqueue(listener, child) /* child enqueued on dead listener */
+
+smc_close_active() flushes only tcp_listen_work. Work items already
+dispatched onto smc_hs_wq for the CLC handshake continue running
+unguarded. smc_accept_enqueue() takes a sock_hold() on the child that
+is never released, so the child smc_sock, its clcsock, and the
+reference all leak. A remote peer that opens TCP connections while the
+server calls close() can exhaust kernel memory.
+
+Move lock_sock_nested() to before the sk_state check so that the test
+and the enqueue are atomic under the listener lock.
+
+Fixes: fd57770dd198 ("net/smc: wait for pending work before clcsock release_sock")
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Link: https://patch.msgid.link/20260803070701.126339-1-sidraya@linux.ibm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index b5db69073e20f..00403175b7406 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1931,11 +1931,12 @@ static void smc_listen_out(struct smc_sock *new_smc)
+               atomic_dec(&lsmc->queued_smc_hs);
+       release_sock(newsmcsk); /* lock in smc_listen_work() */
++      lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+       if (lsmc->sk.sk_state == SMC_LISTEN) {
+-              lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+               smc_accept_enqueue(&lsmc->sk, newsmcsk);
+               release_sock(&lsmc->sk);
+       } else { /* no longer listening */
++              release_sock(&lsmc->sk);
+               smc_close_non_accepted(newsmcsk);
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-stmmac-resume-phy-before-hardware-setup-when-ope.patch b/queue-7.1/net-stmmac-resume-phy-before-hardware-setup-when-ope.patch
new file mode 100644 (file)
index 0000000..8d80b1d
--- /dev/null
@@ -0,0 +1,79 @@
+From 864caafd74b5177920c7d255f952d787166475b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 11:51:56 +0200
+Subject: net: stmmac: resume PHY before hardware setup when opening the
+ interface
+
+From: Stefan Agner <stefan@agner.ch>
+
+[ Upstream commit 06232cb44bc8e81adc2f1d40a01bed830b607ea2 ]
+
+Since the referenced commit, changing the MTU on a running interface no
+longer disconnects and reconnects the PHY; __stmmac_release() merely
+stops phylink, which also suspends the PHY (BMCR power-down) when WoL
+is not enabled. __stmmac_open() then performs the DMA software reset in
+stmmac_hw_setup() before phylink_start() resumes the PHY again.
+
+IEEE 802.3 22.2.4.1.5 allows a PHY to stop its receive clock while
+powered down, and stmmac requires a running receive clock for the DMA
+software reset to complete (the phylink config sets mac_requires_rxc).
+On such setups, e.g. the RK3566-based Home Assistant Green with an
+RTL8211F-VD PHY in RGMII mode, any runtime MTU change now times out and
+leaves the interface dead:
+
+  rk_gmac-dwmac fe010000.ethernet end0: Failed to reset the dma
+  rk_gmac-dwmac fe010000.ethernet end0: stmmac_hw_setup: DMA engine initialization failed
+  rk_gmac-dwmac fe010000.ethernet end0: __stmmac_open: Hw setup failed
+  rk_gmac-dwmac fe010000.ethernet end0: failed reopening the interface after MTU change
+
+In the field this is triggered by NetworkManager applying an MTU while
+activating the connection, breaking networking entirely. The same
+regression has also been reported on i.MX8MP and reproduced on SoCFPGA
+based systems.
+
+Resume the PHY in __stmmac_open() before the hardware setup, making it
+the counterpart of the phylink_stop() in __stmmac_release(), like
+stmmac_resume() already does for the same reason. phylink_start() also
+resumes the PHY, but only after stmmac_hw_setup(), and it cannot be
+moved before the hardware setup since it may bring the link up
+immediately from a workqueue, racing with the initialization (see the
+comment in stmmac_resume()). For the regular ndo_open path the PHY has
+just been attached and is not suspended, in which case
+phylink_prepare_resume() does nothing.
+
+Fixes: db299a0c09e9 ("net: stmmac: move PHY handling out of __stmmac_open()/release()")
+Link: https://github.com/home-assistant/operating-system/issues/4858
+Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Signed-off-by: Stefan Agner <stefan@agner.ch>
+Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260803095156.132827-1-stefan@agner.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index b7e3f652501e4..84e783f87b3d0 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -4132,6 +4132,15 @@ static int __stmmac_open(struct net_device *dev,
+                       dma_conf->tx_queue[i].tbs = priv->dma_conf.tx_queue[i].tbs;
+       memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf));
++      /* The PHY is suspended when the interface is reopened without
++       * disconnecting the PHY, e.g. on MTU change. IEEE 802.3 allows PHYs
++       * to stop their receive clock while powered down, but the DMA
++       * software reset in stmmac_hw_setup() requires a running receive
++       * clock, and phylink_start() below resumes the PHY only after the
++       * hardware setup. Resume a suspended PHY here first.
++       */
++      phylink_prepare_resume(priv->phylink);
++
+       stmmac_reset_queues_param(priv);
+       ret = stmmac_hw_setup(dev);
+-- 
+2.53.0
+
diff --git a/queue-7.1/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch b/queue-7.1/net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
new file mode 100644 (file)
index 0000000..abfa014
--- /dev/null
@@ -0,0 +1,117 @@
+From f6cef5121c15efac07e50e2bc3bcdd99740bb8e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:38:50 +0000
+Subject: net: thunderbolt: Tear down DMA paths before stopping the rings
+
+From: Fan XinRan <shinjiangjiang@gmail.com>
+
+[ Upstream commit 68bf02b6b4ad3f748c6db71fd77b6c0402d252f4 ]
+
+tbnet_tear_down() stops both rings and frees their frame buffers before
+calling tb_xdomain_disable_paths().  tb_ring_stop() zeroes the ring's
+descriptor base and tbnet_free_buffers() unmaps and frees the pages the
+frames sit in, so by the time __tb_path_deactivate_hop() polls the hop's
+'pending' bit, anything still in flight has nowhere to drain to.
+
+The teardown sequence has been in this order since the driver was added.
+The setup path has not: commit ff7cd07f3064 ("net: thunderbolt: Enable
+DMA paths only after rings are enabled") moved the path enable to the end
+of tbnet_connected_work() and documented why:
+
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
+        */
+
+Teardown was never updated to match, so the rings and the paths now come
+down in the same order they go up instead of in reverse.
+
+On an ASMedia ASM4242 host router the 'pending' bit then never clears:
+every teardown burns the full 500 ms timeout and
+__tb_path_deactivate_hop() returns -ETIMEDOUT.  Raising the timeout to
+5 s does not help, so the hop is not slow to drain, it never drains
+at all.
+
+The failure is invisible above the thunderbolt core.
+__tb_path_deactivate_hops() is void and only calls tb_port_warn();
+tb_path_deactivate(), tb_tunnel_deactivate() and
+__tb_disconnect_xdomain_paths() are void as well, and
+tb_disconnect_xdomain_paths() ends in an unconditional "return 0".  So
+tb_xdomain_disable_paths() reports success and the netdev_warn() below
+it never fires.  Repeated teardowns eventually take the XDomain control
+channel down, after which the peer node is gone and only a power cycle
+brings the controller back.
+
+Deactivating the paths first fixes it.  Measured with kretprobes on a
+stock v6.17 tree with no other patches applied, on a link that was up
+and had just carried traffic:
+
+  before: __tb_path_deactivate_hop() returns 0 for the first hop, then
+          -ETIMEDOUT for the second 500335 us later
+  after:  0 for both, 525 us apart
+
+Alternating the two orderings ABBA over three load levels, four
+teardowns per arm: every teardown failed before the change (21 of 21
+that ran), none failed after (0 of 24).  The before arms ran short
+because the link died partway through.  The same split shows up when
+the interface is enslaved to a bond instead of just brought down, which
+is how I ran into this in the first place.  Throughput and latency after
+the change are unchanged.
+
+Hosts whose routers drain the hop despite the stale descriptor base see
+no functional difference, since the paths end up deactivated either way.
+
+Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
+Signed-off-by: Fan XinRan <shinjiangjiang@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260803-b4-tbnet-teardown-v2-1-27de6a13ca2d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index 0cd98496d135d..fb569c0abf8e6 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -390,11 +390,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+                               break;
+               }
+-              tb_ring_stop(net->rx_ring.ring);
+-              tb_ring_stop(net->tx_ring.ring);
+-              tbnet_free_buffers(&net->rx_ring);
+-              tbnet_free_buffers(&net->tx_ring);
+-
++              /* Tear the paths down before stopping the rings.  This mirrors
++               * tbnet_connected_work(), which enables the paths last so the
++               * Rx ring is primed before packets can arrive.  Stopping a
++               * ring zeroes its descriptor base and tbnet_free_buffers()
++               * unmaps and frees the frame buffers, leaving anything still
++               * in flight with nowhere to drain to;
++               * __tb_path_deactivate_hop() then waits for the hop's
++               * 'pending' bit, which on some host routers never clears in
++               * that state.
++               */
+               ret = tb_xdomain_disable_paths(net->xd,
+                                              net->local_transmit_path,
+                                              net->tx_ring.ring->hop,
+@@ -403,6 +408,11 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
+               if (ret)
+                       netdev_warn(net->dev, "failed to disable DMA paths\n");
++              tb_ring_stop(net->rx_ring.ring);
++              tb_ring_stop(net->tx_ring.ring);
++              tbnet_free_buffers(&net->rx_ring);
++              tbnet_free_buffers(&net->tx_ring);
++
+               tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+               net->remote_transmit_path = 0;
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/netfilter-ipset-switch-ext_size-to-atomic64_t.patch b/queue-7.1/netfilter-ipset-switch-ext_size-to-atomic64_t.patch
new file mode 100644 (file)
index 0000000..54e1d65
--- /dev/null
@@ -0,0 +1,134 @@
+From 2ab0a5f88709cd8032896e9952f0b3ee7b223f17 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 20:38:50 +0200
+Subject: netfilter: ipset: switch ext_size to atomic64_t
+
+From: Jozsef Kadlecsik <kadlec@netfilter.org>
+
+[ Upstream commit 712a6f545c359b427daa9a5a782e30d2f8331e25 ]
+
+The hash types do not acquire set->lock, they use 'region locking' where
+only part of the hash table is locked. Parallel inserts and deletes are
+possible and CPUs can race on ->ext_size update.  Switch to atomic64_t.
+
+This leaves another bug unresolved: there still can be a race on
+comment extension re-init.  This will be handled in a later commit
+when converting to rhashtable backend.
+
+Fixes: f66ee0410b1c ("netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports")
+Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netfilter/ipset/ip_set.h  | 2 +-
+ net/netfilter/ipset/ip_set_bitmap_gen.h | 4 ++--
+ net/netfilter/ipset/ip_set_core.c       | 6 +++---
+ net/netfilter/ipset/ip_set_hash_gen.h   | 2 +-
+ net/netfilter/ipset/ip_set_list_set.c   | 4 ++--
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
+index b98331572ad29..cadae9b2578f1 100644
+--- a/include/linux/netfilter/ipset/ip_set.h
++++ b/include/linux/netfilter/ipset/ip_set.h
+@@ -273,7 +273,7 @@ struct ip_set {
+       /* Number of elements (vs timeout) */
+       u32 elements;
+       /* Size of the dynamic extensions (vs timeout) */
+-      size_t ext_size;
++      atomic64_t ext_size;
+       /* Element data size */
+       size_t dsize;
+       /* Offsets to extensions in elements */
+diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
+index bb9b5bed10e19..226fdf17b6832 100644
+--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
++++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
+@@ -77,7 +77,7 @@ mtype_flush(struct ip_set *set)
+               mtype_ext_cleanup(set);
+       bitmap_zero(map->members, map->elements);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ /* Calculate the actual memory size of the set data */
+@@ -93,7 +93,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct mtype *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = mtype_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index 6cfad152d7d1b..822a53a7f502a 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -350,7 +350,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       size_t len = ext->comment ? strlen(ext->comment) : 0;
+       if (unlikely(c)) {
+-              set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++              atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+               rcu_assign_pointer(comment->c, NULL);
+               kfree_rcu(c, rcu);
+       }
+@@ -362,7 +362,7 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
+       if (unlikely(!c))
+               return;
+       strscpy(c->str, ext->comment, len + 1);
+-      set->ext_size += sizeof(*c) + strlen(c->str) + 1;
++      atomic64_add(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, c);
+ }
+ EXPORT_SYMBOL_GPL(ip_set_init_comment);
+@@ -392,7 +392,7 @@ ip_set_comment_free(struct ip_set *set, void *ptr)
+       c = rcu_dereference_protected(comment->c, 1);
+       if (unlikely(!c))
+               return;
+-      set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
++      atomic64_sub(sizeof(*c) + strlen(c->str) + 1, &set->ext_size);
+       rcu_assign_pointer(comment->c, NULL);
+       kfree_rcu(c, rcu);
+ }
+diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
+index a3ed683cc47e7..3072b4e288537 100644
+--- a/net/netfilter/ipset/ip_set_hash_gen.h
++++ b/net/netfilter/ipset/ip_set_hash_gen.h
+@@ -1288,7 +1288,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+-      memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
++      memsize = mtype_ahash_memsize(h, t) + ext_size + atomic64_read(&set->ext_size);
+       htable_bits = t->htable_bits;
+       rcu_read_unlock_bh();
+diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
+index 1cef84f15e8c7..ca3ef9479e838 100644
+--- a/net/netfilter/ipset/ip_set_list_set.c
++++ b/net/netfilter/ipset/ip_set_list_set.c
+@@ -421,7 +421,7 @@ list_set_flush(struct ip_set *set)
+       list_for_each_entry_safe(e, n, &map->members, list)
+               list_set_del(set, e);
+       set->elements = 0;
+-      set->ext_size = 0;
++      atomic64_set(&set->ext_size, 0);
+ }
+ static void
+@@ -455,7 +455,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
+ {
+       const struct list_set *map = set->data;
+       struct nlattr *nested;
+-      size_t memsize = list_set_memsize(map, set->dsize) + set->ext_size;
++      size_t memsize = list_set_memsize(map, set->dsize) + atomic64_read(&set->ext_size);
+       nested = nla_nest_start(skb, IPSET_ATTR_DATA);
+       if (!nested)
+-- 
+2.53.0
+
diff --git a/queue-7.1/netfilter-nf_flow_table-drop-existing-skb-dst-before.patch b/queue-7.1/netfilter-nf_flow_table-drop-existing-skb-dst-before.patch
new file mode 100644 (file)
index 0000000..ef4a75b
--- /dev/null
@@ -0,0 +1,69 @@
+From b5ebd4fc676c67f1e80fe03cfcf0836179695c00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 09:33:28 +0000
+Subject: netfilter: nf_flow_table: drop existing skb dst before
+ skb_dst_set_noref()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 8aecf0bbcc72605592134c917c222207d8f63ab0 ]
+
+Incoming skbs passing through netfilter flowtable offload hooks (or XFRM
+offload path) might already carry a ref-counted dst_entry assigned during
+earlier RX or routing steps.
+
+Calling skb_dst_set_noref() when skb already holds a ref-counted dst
+overwrites skb->_skb_refdst, leaking the previous dst_entry reference
+count and triggering a DEBUG_NET_WARN_ON_ONCE assertion in
+skb_dst_check_unset():
+
+  WARNING: at skb_dst_check_unset include/linux/skbuff.h:1170
+  WARNING: at skb_dst_set_noref include/linux/skbuff.h:1234
+  WARNING: at nf_flow_offload_ip_hook+0xf6c/0x2b60 net/netfilter/nf_flow_table_ip.c:864
+
+Drop any existing dst_entry reference with skb_dst_drop(skb) before
+setting the non-referenced flowtable destination.
+
+Fixes: 2a79fd3908ac ("netfilter: nf_flow_table: attach dst to skbs")
+Reported-by: syzbot+76d4e3a055aec3b007ec@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a71b141.9511d2ce.1fc5b9.033b.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Link: https://patch.msgid.link/20260804093328.1831847-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_flow_table_ip.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
+index 0b78decce8a9b..c9e332fafcb5c 100644
+--- a/net/netfilter/nf_flow_table_ip.c
++++ b/net/netfilter/nf_flow_table_ip.c
+@@ -310,6 +310,7 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+                                     struct dst_entry *dst)
+ {
+       skb_orphan(skb);
++      skb_dst_drop(skb);
+       skb_dst_set_noref(skb, dst);
+       dst_output(state->net, state->sk, skb);
+       return NF_STOLEN;
+@@ -861,6 +862,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
+                       return NF_DROP;
+               }
+               xmit.dest = neigh->ha;
++              skb_dst_drop(skb);
+               skb_dst_set_noref(skb, &rt->dst);
+               break;
+       case FLOW_OFFLOAD_XMIT_DIRECT:
+@@ -1178,6 +1180,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+                       return NF_DROP;
+               }
+               xmit.dest = neigh->ha;
++              skb_dst_drop(skb);
+               skb_dst_set_noref(skb, &rt->dst);
+               break;
+       case FLOW_OFFLOAD_XMIT_DIRECT:
+-- 
+2.53.0
+
diff --git a/queue-7.1/nfs-decrement-refcounts-if-allocating-nfs_free_state.patch b/queue-7.1/nfs-decrement-refcounts-if-allocating-nfs_free_state.patch
new file mode 100644 (file)
index 0000000..83548b2
--- /dev/null
@@ -0,0 +1,70 @@
+From 557122a1aabb258ed59ba1081371c35506308d86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 15:39:45 -0400
+Subject: NFS: Decrement refcounts if allocating nfs_free_stateid_data fails
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit 4aeb63d5ac2dba2a474e7b64d60776d9dd1c6cd2 ]
+
+I noticed that we were immediately exiting this function if the
+allocation fails, leaving the client and server object refcounts bumped.
+Fix this by creating a common exit point to clean up dangling
+references.
+
+Fixes: 576acc259146 ("nfs4: take a reference on the nfs_client when running FREE_STATEID")
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index bea00343f09b1..6142a7daf983d 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10369,21 +10369,22 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       struct nfs_free_stateid_data *data;
+       struct rpc_task *task;
+       struct nfs_client *clp = server->nfs_client;
++      int ret = -EIO;
+       if (!refcount_inc_not_zero(&clp->cl_count))
+-              return -EIO;
+-      if (!nfs_sb_active(server->super)) {
+-              nfs_put_client(clp);
+-              return -EIO;
+-      }
++              return ret;
++      if (!nfs_sb_active(server->super))
++              goto out_put_clp;
+       nfs4_state_protect(clp, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+       dprintk("NFS call  free_stateid %p\n", stateid);
+       data = kmalloc_obj(*data);
+-      if (!data)
+-              return -ENOMEM;
++      if (!data) {
++              ret = -ENOMEM;
++              goto out_put_server;
++      }
+       data->server = server;
+       nfs4_stateid_copy(&data->args.stateid, stateid);
+@@ -10399,6 +10400,11 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       rpc_put_task(task);
+       stateid->type = NFS4_FREED_STATEID_TYPE;
+       return 0;
++out_put_server:
++      nfs_sb_deactive(server->super);
++out_put_clp:
++      nfs_put_client(clp);
++      return ret;
+ }
+ static void
+-- 
+2.53.0
+
diff --git a/queue-7.1/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch b/queue-7.1/nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
new file mode 100644 (file)
index 0000000..f870c86
--- /dev/null
@@ -0,0 +1,50 @@
+From f85aa6110cf116d3a602a9a605740ba8a021c012 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jun 2026 14:31:00 -0400
+Subject: NFS: Pin the 'struct nfs_server' during a FREE_STATEID call
+
+From: Anna Schumaker <anna.schumaker@hammerspace.com>
+
+[ Upstream commit cf616096a0f3a2b60f7d68b6b39674a6867ded9c ]
+
+Dan Aloni reports that he was able to hit a use-after-free bug if a
+FREE_STATEID operation gets delayed for whatever reason. Fix this by
+bumping the refcount of the 'struct nfs_server' object for the duration
+of the FREE_STATEID so it doesn't get cleaned up from underneath us
+while operations are still in flight.
+
+Reported-by: Dan Aloni <dan.aloni@vastdata.com>
+Fixes: 7c1d5fae4a87 ("NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call")
+Tested-by: Dan Aloni <dan.aloni@vastdata.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 4db27f4eb01e9..bea00343f09b1 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10330,6 +10330,7 @@ static void nfs41_free_stateid_release(void *calldata)
+       struct nfs_free_stateid_data *data = calldata;
+       struct nfs_client *clp = data->server->nfs_client;
++      nfs_sb_deactive(data->server->super);
+       nfs_put_client(clp);
+       kfree(calldata);
+ }
+@@ -10371,6 +10372,10 @@ static int nfs41_free_stateid(struct nfs_server *server,
+       if (!refcount_inc_not_zero(&clp->cl_count))
+               return -EIO;
++      if (!nfs_sb_active(server->super)) {
++              nfs_put_client(clp);
++              return -EIO;
++      }
+       nfs4_state_protect(clp, NFS_SP4_MACH_CRED_STATEID,
+               &task_setup.rpc_client, &msg);
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-add-missing-rtnl_link_ops-get_size-callback.patch b/queue-7.1/ovpn-add-missing-rtnl_link_ops-get_size-callback.patch
new file mode 100644 (file)
index 0000000..296e981
--- /dev/null
@@ -0,0 +1,56 @@
+From 0c7b865a1c9176fd8aa9f6d2379cc48b28cbaf5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jul 2026 15:41:30 +0200
+Subject: ovpn: add missing rtnl_link_ops->get_size callback
+
+From: Ralf Lici <ralf@mandelbit.com>
+
+[ Upstream commit 6e9f539e4f01153651dd77609b5ccadd44b74df8 ]
+
+ovpn_fill_info emits IFLA_OVPN_MODE inside IFLA_INFO_DATA, but
+ovpn_link_ops does not provide a get_size callback. Consequently,
+rtnetlink's size estimate for ovpn link messages does not include the
+nested mode attribute.
+
+Available skb tailroom may hide this mismatch. When the remaining space
+is insufficient, however, ovpn_fill_info returns -EMSGSIZE and message
+construction fails.
+
+Add the callback and account for IFLA_OVPN_MODE.
+
+Fixes: c2d950c4672a ("ovpn: add basic interface creation/destruction/management routines")
+Signed-off-by: Ralf Lici <ralf@mandelbit.com>
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/main.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c
+index 9993c1dfe471d..9d9a0ff690d66 100644
+--- a/drivers/net/ovpn/main.c
++++ b/drivers/net/ovpn/main.c
+@@ -210,6 +210,12 @@ static int ovpn_newlink(struct net_device *dev,
+       return register_netdevice(dev);
+ }
++static size_t ovpn_get_size(const struct net_device *dev)
++{
++      /* IFLA_OVPN_MODE */
++      return nla_total_size(sizeof(u8));
++}
++
+ static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev)
+ {
+       struct ovpn_priv *ovpn = netdev_priv(dev);
+@@ -228,6 +234,7 @@ static struct rtnl_link_ops ovpn_link_ops = {
+       .policy = ovpn_policy,
+       .maxtype = IFLA_OVPN_MAX,
+       .newlink = ovpn_newlink,
++      .get_size = ovpn_get_size,
+       .fill_info = ovpn_fill_info,
+ };
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-disable-ipv4-redirects-on-mp-interfaces.patch b/queue-7.1/ovpn-disable-ipv4-redirects-on-mp-interfaces.patch
new file mode 100644 (file)
index 0000000..816d2ac
--- /dev/null
@@ -0,0 +1,130 @@
+From 82be98162c3adc0e61c050372f13cd9ac88f819a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:53 +0200
+Subject: ovpn: disable IPv4 redirects on MP interfaces
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 0301aa324941698bec3dd455df1c5abc7afb10db ]
+
+ovpn_mp_alloc() tried to disable SEND_REDIRECTS on a multipeer
+interface, but it runs from ovpn_net_init() (->ndo_init), which
+register_netdevice() invokes before the NETDEV_REGISTER notifier
+chain. The IPv4 in_device is only created when that notifier reaches
+inetdev_event() -> inetdev_init(), so __in_dev_get_rtnl() always
+returned NULL at ndo_init time and the whole redirect-disabling block
+(both the per-device and the per-netns IPV4_DEVCONF_ALL write) was
+dead. MP interfaces therefore kept emitting ICMP redirects.
+
+Disabling redirects only once is not enough either: the IPv4
+in_device is destroyed and recreated when the interface is moved to a
+different network namespace (NETDEV_UNREGISTER/NETDEV_REGISTER), and
+the newly created in_device inherits the destination namespace
+defaults, silently re-enabling SEND_REDIRECTS.
+
+Disable redirects from ovpn_net_open() (->ndo_open) instead: it runs
+every time the interface is brought up, including after the in_device
+has been recreated, so the setting is always re-applied. This mirrors
+what wireguard does in wg_open(). RTNL is held on the ndo_open() path,
+so __in_dev_get_rtnl() is safe.
+
+Fixes: 05003b408c20 ("ovpn: implement multi-peer support")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/main.c | 50 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 35 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c
+index 9d9a0ff690d66..3a04757d5c31e 100644
+--- a/drivers/net/ovpn/main.c
++++ b/drivers/net/ovpn/main.c
+@@ -35,25 +35,11 @@ static void ovpn_priv_free(struct net_device *net)
+ static int ovpn_mp_alloc(struct ovpn_priv *ovpn)
+ {
+-      struct in_device *dev_v4;
+       int i;
+       if (ovpn->mode != OVPN_MODE_MP)
+               return 0;
+-      dev_v4 = __in_dev_get_rtnl(ovpn->dev);
+-      if (dev_v4) {
+-              /* disable redirects as Linux gets confused by ovpn
+-               * handling same-LAN routing.
+-               * This happens because a multipeer interface is used as
+-               * relay point between hosts in the same subnet, while
+-               * in a classic LAN this would not be needed because the
+-               * two hosts would be able to talk directly.
+-               */
+-              IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false);
+-              IPV4_DEVCONF_ALL(dev_net(ovpn->dev), SEND_REDIRECTS) = false;
+-      }
+-
+       /* the peer container is fairly large, therefore we allocate it only in
+        * MP mode
+        */
+@@ -97,9 +83,38 @@ static void ovpn_net_uninit(struct net_device *dev)
+       gro_cells_destroy(&ovpn->gro_cells);
+ }
++static int ovpn_net_open(struct net_device *dev)
++{
++      struct ovpn_priv *ovpn = netdev_priv(dev);
++      struct in_device *dev_v4;
++
++      /* the IPv4 in_device (and thus its config) is recreated whenever the
++       * interface is moved to a new netns, so redirects must be disabled on
++       * every bring-up rather than once at creation time, otherwise the
++       * setting is silently lost after such a move
++       */
++      if (ovpn->mode == OVPN_MODE_MP) {
++              dev_v4 = __in_dev_get_rtnl(dev);
++              if (dev_v4) {
++                      /* disable redirects as Linux gets confused by ovpn
++                       * handling same-LAN routing.
++                       * This happens because a multipeer interface is used as
++                       * relay point between hosts in the same subnet, while
++                       * in a classic LAN this would not be needed because the
++                       * two hosts would be able to talk directly.
++                       */
++                      IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false);
++                      IPV4_DEVCONF_ALL(dev_net(dev), SEND_REDIRECTS) = false;
++              }
++      }
++
++      return 0;
++}
++
+ static const struct net_device_ops ovpn_netdev_ops = {
+       .ndo_init               = ovpn_net_init,
+       .ndo_uninit             = ovpn_net_uninit,
++      .ndo_open               = ovpn_net_open,
+       .ndo_start_xmit         = ovpn_net_xmit,
+ };
+@@ -183,6 +198,7 @@ static int ovpn_newlink(struct net_device *dev,
+       struct ovpn_priv *ovpn = netdev_priv(dev);
+       struct nlattr **data = params->data;
+       enum ovpn_mode mode = OVPN_MODE_P2P;
++      int ret;
+       if (data && data[IFLA_OVPN_MODE]) {
+               mode = nla_get_u8(data[IFLA_OVPN_MODE]);
+@@ -207,7 +223,11 @@ static int ovpn_newlink(struct net_device *dev,
+       else
+               netif_carrier_off(dev);
+-      return register_netdevice(dev);
++      ret = register_netdevice(dev);
++      if (ret < 0)
++              return ret;
++
++      return 0;
+ }
+ static size_t ovpn_get_size(const struct net_device *dev)
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch b/queue-7.1/ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch
new file mode 100644 (file)
index 0000000..e66d8bd
--- /dev/null
@@ -0,0 +1,47 @@
+From 2bc6639f6aedc0298d99cee731f177e9d59c4842 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:50 +0200
+Subject: ovpn: ensure socket is owned by ovpn before deref sk_user_data
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 59aed1eb60d70678a53acccb0cb337a26ce6680e ]
+
+Some subsystems, like BPF SOCKMAP, set sk_user_data without
+actually setting the encap_type.
+
+For this reason, we must make sure that the type is the
+one ovpn expects before dereferencing sk_user_data.
+
+Failing to do so may lead to out-of-bounds reads.
+
+Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/socket.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/net/ovpn/socket.c b/drivers/net/ovpn/socket.c
+index 517caa64a4fef..6cbeb2caaeeca 100644
+--- a/drivers/net/ovpn/socket.c
++++ b/drivers/net/ovpn/socket.c
+@@ -162,6 +162,15 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer)
+               rcu_read_lock();
+               ovpn_sock = rcu_dereference_sk_user_data(sk);
+               if (ovpn_sock) {
++                      /* something else filled the sk_user_data without
++                       * setting the encap_type. Reject the socket.
++                       */
++                      if (!type) {
++                              ovpn_sock = ERR_PTR(-EBUSY);
++                              rcu_read_unlock();
++                              goto sock_release;
++                      }
++
+                       /* socket owned by another ovpn instance, we can't use it */
+                       if (ovpn_sock->ovpn != peer->ovpn) {
+                               ovpn_sock = ERR_PTR(-EBUSY);
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-ensure-tcp-vars-are-initialized-first.patch b/queue-7.1/ovpn-ensure-tcp-vars-are-initialized-first.patch
new file mode 100644 (file)
index 0000000..777ba8a
--- /dev/null
@@ -0,0 +1,52 @@
+From efa66673615423e554e6863afc30577aedeef384 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:54 +0200
+Subject: ovpn: ensure TCP vars are initialized first
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 4680c0ebd958fc18e53c8b91d80436b236a8fc09 ]
+
+Netlink calls may access TCP global vars (i.e. when attaching
+a TCP socket), therefore we need to make sure the
+latters are initialized beforehand.
+
+For this reason move the global TCP initialization at the top
+of the module init function.
+
+Fixes: 11851cbd60ea ("ovpn: implement TCP transport")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/main.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c
+index 3a04757d5c31e..168cfe9b59a98 100644
+--- a/drivers/net/ovpn/main.c
++++ b/drivers/net/ovpn/main.c
+@@ -260,8 +260,11 @@ static struct rtnl_link_ops ovpn_link_ops = {
+ static int __init ovpn_init(void)
+ {
+-      int err = rtnl_link_register(&ovpn_link_ops);
++      int err;
++      ovpn_tcp_init();
++
++      err = rtnl_link_register(&ovpn_link_ops);
+       if (err) {
+               pr_err("ovpn: can't register rtnl link ops: %d\n", err);
+               return err;
+@@ -273,8 +276,6 @@ static int __init ovpn_init(void)
+               goto unreg_rtnl;
+       }
+-      ovpn_tcp_init();
+-
+       return 0;
+ unreg_rtnl:
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-fix-incorrect-use-of-rcu_access_pointer.patch b/queue-7.1/ovpn-fix-incorrect-use-of-rcu_access_pointer.patch
new file mode 100644 (file)
index 0000000..3d0f6d5
--- /dev/null
@@ -0,0 +1,37 @@
+From fe27bda44071c62e5cc36dceccd4924bda6029c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 09:49:26 +0800
+Subject: ovpn: fix incorrect use of rcu_access_pointer()
+
+From: Qingfang Deng <qingfang.deng@linux.dev>
+
+[ Upstream commit 26ba17d845193dac4921ae1ab280d28d1938052e ]
+
+rcu_access_pointer() should only be used to test the value of a pointer,
+not to dereference it. As it's in a spin_lock_bh() critical section, use
+rcu_dereference_bh() instead, avoiding an extra rcu_read_lock().
+
+Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object")
+Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index eada414a9d922..b0519f9840d83 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -1249,7 +1249,7 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk,
+       }
+       if (sk) {
+-              ovpn_sock = rcu_access_pointer(peer->sock);
++              ovpn_sock = rcu_dereference_bh(peer->sock);
+               if (!ovpn_sock || ovpn_sock->sk != sk) {
+                       spin_unlock_bh(&ovpn->lock);
+                       return;
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-hash-floated-peer-by-transport-identity-only.patch b/queue-7.1/ovpn-hash-floated-peer-by-transport-identity-only.patch
new file mode 100644 (file)
index 0000000..2cf0913
--- /dev/null
@@ -0,0 +1,94 @@
+From f00e6d56b80aa65b348f37f53a4d7f2f600cc304 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:52 +0200
+Subject: ovpn: hash floated peer by transport identity only
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit b47a52dcd598a50207a33df304acdf45348a690f ]
+
+The by_transp_addr table is keyed on the peer's remote transport
+address, but the float rehash hashed bind->remote directly, while the
+two other sites that touch the table build a clean key first:
+ovpn_peer_add_mp() and the lookup in ovpn_peer_get_by_transp_addr()
+both hash a sockaddr holding only family/address/port.
+
+For a link-local IPv6 peer, bind->remote carries sin6_scope_id (set
+from ipv6_iface_scope_id() when the endpoint is learned), and that
+field is folded into the jhash() over sizeof(struct sockaddr_in6).
+The lookup never sets sin6_scope_id, so after such a peer floats it is
+rehashed into a scope_id-dependent bucket that lookups (scope_id 0)
+never visit, making the peer unreachable through the by_transp_addr
+fallback. ovpn_peer_transp_match() only compares address and port, so
+the hash was keying on a field the match ignores.
+
+sin6_scope_id must stay in bind->remote because the TX path uses it as
+flowi6_oif, so it cannot just be cleared there. Instead build the hash
+key from family/address/port only, exactly like ovpn_peer_add_mp() and
+the lookup, so all three sites agree on the bucket.
+
+Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index 33fb0a75e6006..eada414a9d922 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -904,7 +904,10 @@ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
+ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
+                                        const struct ovpn_bind *bind)
+ {
++      struct sockaddr_storage sa = {};
+       struct hlist_nulls_head *nhead;
++      struct sockaddr_in6 *sa6;
++      struct sockaddr_in *sa4;
+       size_t salen;
+       lockdep_assert_held(&peer->ovpn->lock);
+@@ -920,12 +923,26 @@ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
+       if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
+               return;
++      /* Build the hash key from the transport identity only
++       * (family/address/port), matching ovpn_peer_add_mp() and the lookup
++       * in ovpn_peer_get_by_transp_addr(). Hashing bind->remote directly
++       * would fold in sin6_scope_id (set on the float path but never by the
++       * lookup), scattering the peer into a bucket lookups cannot reach.
++       */
+       switch (bind->remote.in4.sin_family) {
+       case AF_INET:
+-              salen = sizeof(struct sockaddr_in);
++              sa4 = (struct sockaddr_in *)&sa;
++              sa4->sin_family = AF_INET;
++              sa4->sin_addr.s_addr = bind->remote.in4.sin_addr.s_addr;
++              sa4->sin_port = bind->remote.in4.sin_port;
++              salen = sizeof(*sa4);
+               break;
+       case AF_INET6:
+-              salen = sizeof(struct sockaddr_in6);
++              sa6 = (struct sockaddr_in6 *)&sa;
++              sa6->sin6_family = AF_INET6;
++              sa6->sin6_addr = bind->remote.in6.sin6_addr;
++              sa6->sin6_port = bind->remote.in6.sin6_port;
++              salen = sizeof(*sa6);
+               break;
+       default:
+               return;
+@@ -934,8 +951,8 @@ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
+       /* remove old hashing (no-op if entry is not currently linked) */
+       hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
+       /* re-add with current transport address */
+-      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
+-                                 &bind->remote, salen);
++      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, &sa,
++                                 salen);
+       hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch b/queue-7.1/ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch
new file mode 100644 (file)
index 0000000..b8b53ec
--- /dev/null
@@ -0,0 +1,215 @@
+From 85fef0824e3cabf31500f5a1f066ab99b08c366e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:48 +0200
+Subject: ovpn: rehash peer in by_transp_addr table on CMD_PEER_SET
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit cc12f7240c8c4dee557749d33237542613992f14 ]
+
+When userspace updates a peer's remote endpoint via OVPN_CMD_PEER_SET,
+ovpn_nl_peer_modify() installs a new ovpn_bind through
+ovpn_peer_reset_sockaddr(), but ovpn_nl_peer_set_doit() only calls
+ovpn_peer_hash_vpn_ip() to refresh the VPN-IP hashtables. The peer is
+left in the bucket of peers->by_transp_addr corresponding to its old
+remote address.
+
+As a consequence, datagrams arriving at the UDP RX path from the newly
+configured remote hash to a different slot and the lockless lookup in
+ovpn_peer_get_by_transp_addr() (called from ovpn_udp_encap_recv()) does
+not find the peer, until either a float event or a peer re-add fixes
+the bucket.
+
+Introduce ovpn_peer_hash_transp_addr() (modeled after
+ovpn_peer_hash_vpn_ip()) and invoke it from ovpn_nl_peer_set_doit()
+whenever the request carried a new remote address. The helper bails
+out in P2P mode and on peers without a bind (TCP), and relies on
+hlist_nulls_del_init_rcu()'s pprev==NULL short-circuit to handle the
+case of an entry not currently linked in the table.
+
+Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/netlink.c |   6 +++
+ drivers/net/ovpn/peer.c    | 105 +++++++++++++++++++++++++------------
+ drivers/net/ovpn/peer.h    |   1 +
+ 3 files changed, 79 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c
+index 4c66c1ec497ec..4dad852941982 100644
+--- a/drivers/net/ovpn/netlink.c
++++ b/drivers/net/ovpn/netlink.c
+@@ -534,6 +534,12 @@ int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info)
+        */
+       if (ret > 0)
+               ovpn_peer_hash_vpn_ip(peer);
++      /* if the remote endpoint was updated, the by_transp_addr hash bucket
++       * also needs to be refreshed, otherwise incoming packets from the new
++       * remote address would fail the lockless lookup
++       */
++      if (attrs[OVPN_A_PEER_REMOTE_IPV4] || attrs[OVPN_A_PEER_REMOTE_IPV6])
++              ovpn_peer_hash_transp_addr(peer);
+       spin_unlock_bh(&ovpn->lock);
+       ovpn_peer_put(peer);
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index 68021c0c17830..a330892e82bf7 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -189,6 +189,9 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer,
+       &(*__tbl1)[ovpn_get_hash_slot(*__tbl1, _key, _key_len)];\
+ })
++static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
++                                       const struct ovpn_bind *bind);
++
+ /**
+  * ovpn_peer_endpoints_update - update remote or local endpoint for peer
+  * @peer: peer to update the remote endpoint for
+@@ -196,7 +199,6 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer,
+  */
+ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+ {
+-      struct hlist_nulls_head *nhead;
+       struct sockaddr_storage ss;
+       struct sockaddr_in6 *sa6;
+       bool reset_cache = false;
+@@ -295,46 +297,23 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+       ovpn_nl_peer_float_notify(peer, &ss);
+       /* rehashing is required only in MP mode as P2P has one peer
+-       * only and thus there is no hashtable
++       * only and thus there is no hashtable.
++       *
++       * This function may be invoked concurrently, so re-read peer->bind
++       * under the proper locks and rehash against its current value.
+        */
+       if (peer->ovpn->mode != OVPN_MODE_MP)
+               return;
++      /* This function may be invoked concurrently, therefore another
++       * float may have happened in parallel: re-acquire the locks and
++       * rehash using the peer->bind->remote directly as key
++       */
+       spin_lock_bh(&peer->ovpn->lock);
+       spin_lock_bh(&peer->lock);
+       bind = rcu_dereference_protected(peer->bind,
+                                        lockdep_is_held(&peer->lock));
+-      if (unlikely(!bind))
+-              goto unlock2;
+-
+-      /* peer may have been concurrently removed between the caller's
+-       * initial lookup and our acquisition of ovpn->lock; skip the
+-       * rehash so we don't re-insert a removed peer
+-       */
+-      if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
+-              goto unlock2;
+-
+-      /* This function may be invoked concurrently, therefore another
+-       * float may have happened in parallel: perform rehashing
+-       * using the peer->bind->remote directly as key
+-       */
+-
+-      switch (bind->remote.in4.sin_family) {
+-      case AF_INET:
+-              salen = sizeof(*sa);
+-              break;
+-      case AF_INET6:
+-              salen = sizeof(*sa6);
+-              break;
+-      }
+-
+-      /* remove old hashing */
+-      hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
+-      /* re-add with new transport address */
+-      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
+-                                 &bind->remote, salen);
+-      hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
+-unlock2:
++      __ovpn_peer_hash_transp_addr(peer, bind);
+       spin_unlock_bh(&peer->lock);
+       spin_unlock_bh(&peer->ovpn->lock);
+       return;
+@@ -902,6 +881,66 @@ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
+       return match;
+ }
++/* Move @peer to the by_transp_addr bucket matching its current bind.
++ *
++ * Caller must hold both peer->ovpn->lock and peer->lock, and must have
++ * already dereferenced a valid (non-NULL) peer->bind, passed in as @bind.
++ */
++static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer,
++                                       const struct ovpn_bind *bind)
++{
++      struct hlist_nulls_head *nhead;
++      size_t salen;
++
++      lockdep_assert_held(&peer->ovpn->lock);
++      lockdep_assert_held(&peer->lock);
++
++      if (WARN_ON_ONCE(!bind))
++              return;
++
++      /* peer may have been concurrently removed between the caller's
++       * initial lookup and our acquisition of ovpn->lock; skip the
++       * rehash so we don't re-insert a removed peer
++       */
++      if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
++              return;
++
++      switch (bind->remote.in4.sin_family) {
++      case AF_INET:
++              salen = sizeof(struct sockaddr_in);
++              break;
++      case AF_INET6:
++              salen = sizeof(struct sockaddr_in6);
++              break;
++      default:
++              return;
++      }
++
++      /* remove old hashing (no-op if entry is not currently linked) */
++      hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
++      /* re-add with current transport address */
++      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
++                                 &bind->remote, salen);
++      hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
++}
++
++void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer)
++{
++      struct ovpn_bind *bind;
++
++      lockdep_assert_held(&peer->ovpn->lock);
++
++      /* rehashing makes sense only in multipeer mode */
++      if (peer->ovpn->mode != OVPN_MODE_MP)
++              return;
++
++      spin_lock_bh(&peer->lock);
++      bind = rcu_dereference_protected(peer->bind,
++                                       lockdep_is_held(&peer->lock));
++      __ovpn_peer_hash_transp_addr(peer, bind);
++      spin_unlock_bh(&peer->lock);
++}
++
+ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer)
+ {
+       struct hlist_nulls_head *nhead;
+diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h
+index 86c8cffada6d4..dfa5c0037e02b 100644
+--- a/drivers/net/ovpn/peer.h
++++ b/drivers/net/ovpn/peer.h
+@@ -150,6 +150,7 @@ struct ovpn_peer *ovpn_peer_get_by_id(struct ovpn_priv *ovpn, u32 peer_id);
+ struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn,
+                                      struct sk_buff *skb);
+ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer);
++void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer);
+ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
+                           struct ovpn_peer *peer);
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch b/queue-7.1/ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch
new file mode 100644 (file)
index 0000000..13147f6
--- /dev/null
@@ -0,0 +1,142 @@
+From aeeed7a742d1a79b21e9ac45083e673c27ab54a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:47 +0200
+Subject: ovpn: skip rehash for peers already removed from by_id
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 33ec10567fe14456063daf549fdf1a4f53448e4c ]
+
+ovpn_nl_peer_set_doit() resolves the target peer via
+ovpn_peer_get_by_id() before taking ovpn->lock. In the window between
+the lookup (which only takes a refcount) and the subsequent
+spin_lock_bh(&ovpn->lock), a concurrent OVPN_CMD_PEER_DEL, keepalive
+expiry, or socket teardown can take ovpn->lock first, run
+ovpn_peer_remove() to unhash the peer from all four tables (by_id,
+by_vpn_addr4/6, by_transp_addr) and release the lock. set_doit then
+acquires ovpn->lock and calls ovpn_peer_hash_vpn_ip(), which
+re-inserts the now-removed peer back into the rehashing tables.
+
+The same race affects the float path: ovpn_peer_endpoints_update()
+holds only a refcount and acquires ovpn->lock very late (after async
+AEAD decrypt and a netlink notification), then rehashes the peer
+in the by_transp_addr table.
+
+The resurrected peer becomes reachable again from the RX lookup
+(ovpn_peer_get_by_transp_addr) and the TX VPN-IP lookup, even though
+userspace believes it is gone. Once the data-path refcount drops the
+peer is freed via call_rcu while the hash entries embedded in it
+remain linked, opening a UAF window.
+
+Bail out of the rehash when hash_entry_id is unhashed, mirroring
+the sentinel already used by ovpn_peer_remove() to detect the
+already-removed state. The check is safe under ovpn->lock, which
+serializes every mutation of hash_entry_id, and is a no-op for the
+add path because ovpn_peer_add_mp() inserts hash_entry_id before
+calling ovpn_peer_hash_vpn_ip().
+
+Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 73 ++++++++++++++++++++++++-----------------
+ 1 file changed, 43 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index a21d02ac715e0..68021c0c17830 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -297,40 +297,46 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+       /* rehashing is required only in MP mode as P2P has one peer
+        * only and thus there is no hashtable
+        */
+-      if (peer->ovpn->mode == OVPN_MODE_MP) {
+-              spin_lock_bh(&peer->ovpn->lock);
+-              spin_lock_bh(&peer->lock);
+-              bind = rcu_dereference_protected(peer->bind,
+-                                               lockdep_is_held(&peer->lock));
+-              if (unlikely(!bind)) {
+-                      spin_unlock_bh(&peer->lock);
+-                      spin_unlock_bh(&peer->ovpn->lock);
+-                      return;
+-              }
++      if (peer->ovpn->mode != OVPN_MODE_MP)
++              return;
+-              /* This function may be invoked concurrently, therefore another
+-               * float may have happened in parallel: perform rehashing
+-               * using the peer->bind->remote directly as key
+-               */
++      spin_lock_bh(&peer->ovpn->lock);
++      spin_lock_bh(&peer->lock);
++      bind = rcu_dereference_protected(peer->bind,
++                                       lockdep_is_held(&peer->lock));
++      if (unlikely(!bind))
++              goto unlock2;
+-              switch (bind->remote.in4.sin_family) {
+-              case AF_INET:
+-                      salen = sizeof(*sa);
+-                      break;
+-              case AF_INET6:
+-                      salen = sizeof(*sa6);
+-                      break;
+-              }
++      /* peer may have been concurrently removed between the caller's
++       * initial lookup and our acquisition of ovpn->lock; skip the
++       * rehash so we don't re-insert a removed peer
++       */
++      if (unlikely(hlist_unhashed(&peer->hash_entry_id)))
++              goto unlock2;
+-              /* remove old hashing */
+-              hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
+-              /* re-add with new transport address */
+-              nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
+-                                         &bind->remote, salen);
+-              hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
+-              spin_unlock_bh(&peer->lock);
+-              spin_unlock_bh(&peer->ovpn->lock);
++      /* This function may be invoked concurrently, therefore another
++       * float may have happened in parallel: perform rehashing
++       * using the peer->bind->remote directly as key
++       */
++
++      switch (bind->remote.in4.sin_family) {
++      case AF_INET:
++              salen = sizeof(*sa);
++              break;
++      case AF_INET6:
++              salen = sizeof(*sa6);
++              break;
+       }
++
++      /* remove old hashing */
++      hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
++      /* re-add with new transport address */
++      nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
++                                 &bind->remote, salen);
++      hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
++unlock2:
++      spin_unlock_bh(&peer->lock);
++      spin_unlock_bh(&peer->ovpn->lock);
+       return;
+ unlock:
+       spin_unlock_bh(&peer->lock);
+@@ -906,6 +912,13 @@ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer)
+       if (peer->ovpn->mode != OVPN_MODE_MP)
+               return;
++      /* peer may have been concurrently removed between the caller's
++       * initial lookup and our acquisition of ovpn->lock; skip the
++       * rehash so we don't re-insert a removed peer
++       */
++      if (hlist_unhashed(&peer->hash_entry_id))
++              return;
++
+       if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) {
+               /* remove potential old hashing */
+               hlist_nulls_del_init_rcu(&peer->hash_entry_addr4);
+-- 
+2.53.0
+
diff --git a/queue-7.1/ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch b/queue-7.1/ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch
new file mode 100644 (file)
index 0000000..796ceea
--- /dev/null
@@ -0,0 +1,91 @@
+From 80a4f313e8aa5bfcef0f12c1e142086e8836360a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:48:51 +0200
+Subject: ovpn: zero-initialize sockaddr before learning a floated endpoint
+
+From: Antonio Quartulli <antonio@openvpn.net>
+
+[ Upstream commit 3f012bdbabe211ccbc0c50ea5a1dbc60f8af1532 ]
+
+ovpn_peer_endpoints_update() builds the new remote endpoint in an
+on-stack struct sockaddr_storage that is left uninitialized. For IPv4
+only sin_family/sin_addr/sin_port are written, leaving the 8-byte
+sin_zero padding as stack garbage (for IPv6, sin6_flowinfo is left
+uninitialized likewise).
+
+ovpn_peer_reset_sockaddr() -> ovpn_bind_from_sockaddr() then memcpy()s
+sizeof(struct sockaddr_in)/sizeof(struct sockaddr_in6) bytes - padding
+included - into bind->remote. That buffer is later hashed with jhash()
+over the same length to place the peer in the by_transp_addr table, so
+the garbage padding lands the floated peer in an essentially random
+bucket. Lockless lookups in ovpn_peer_get_by_transp_addr() build their
+key from a zero-initialized sockaddr_storage, compute a different bucket
+and fail to find the peer.
+
+This is also a plain use of uninitialized stack memory in jhash().
+
+Build the floated endpoint with a designated initializer so the
+padding (sin_zero for IPv4, sin6_flowinfo for IPv6) is zeroed as part
+of the assignment. This keeps the padding out of the by_transp_addr
+hash key without memset-ing the whole sockaddr_storage on every
+received packet.
+
+Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint")
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ovpn/peer.c | 31 +++++++++++++++++++++++--------
+ 1 file changed, 23 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
+index a330892e82bf7..33fb0a75e6006 100644
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -222,9 +222,16 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+                        */
+                       local_ip = &ip_hdr(skb)->daddr;
+                       sa = (struct sockaddr_in *)&ss;
+-                      sa->sin_family = AF_INET;
+-                      sa->sin_addr.s_addr = ip_hdr(skb)->saddr;
+-                      sa->sin_port = udp_hdr(skb)->source;
++                      /* use a designated initializer so the sin_zero padding
++                       * is zeroed (it ends up in the by_transp_addr hash key)
++                       * without memset-ing the whole sockaddr_storage on the
++                       * RX fast path
++                       */
++                      *sa = (struct sockaddr_in) {
++                              .sin_family = AF_INET,
++                              .sin_addr.s_addr = ip_hdr(skb)->saddr,
++                              .sin_port = udp_hdr(skb)->source,
++                      };
+                       salen = sizeof(*sa);
+                       reset_cache = true;
+                       break;
+@@ -250,11 +257,19 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
+                        */
+                       local_ip = &ipv6_hdr(skb)->daddr;
+                       sa6 = (struct sockaddr_in6 *)&ss;
+-                      sa6->sin6_family = AF_INET6;
+-                      sa6->sin6_addr = ipv6_hdr(skb)->saddr;
+-                      sa6->sin6_port = udp_hdr(skb)->source;
+-                      sa6->sin6_scope_id = ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr,
+-                                                               skb->skb_iif);
++                      /* use a designated initializer so the sin6_flowinfo
++                       * padding is zeroed (it ends up in the by_transp_addr
++                       * hash key) without memset-ing the whole
++                       * sockaddr_storage on the RX fast path
++                       */
++                      *sa6 = (struct sockaddr_in6) {
++                              .sin6_family = AF_INET6,
++                              .sin6_addr = ipv6_hdr(skb)->saddr,
++                              .sin6_port = udp_hdr(skb)->source,
++                              .sin6_scope_id =
++                                      ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr,
++                                                          skb->skb_iif),
++                      };
+                       salen = sizeof(*sa6);
+                       reset_cache = true;
+                       break;
+-- 
+2.53.0
+
diff --git a/queue-7.1/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch b/queue-7.1/pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch
new file mode 100644 (file)
index 0000000..bfb7211
--- /dev/null
@@ -0,0 +1,54 @@
+From b462af1aa7f44fc725c572081a16bb20dee6fea8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 17:00:30 +0000
+Subject: pds_core: cancel pending PCI reset work on AER recovery
+
+From: Nikhil P. Rao <nikhil.rao@amd.com>
+
+[ Upstream commit 57d635329d799b79096155cdf47ee0013d6780d1 ]
+
+pdsc_check_pci_health() queues pci_reset_work when it sees a broken PCI
+connection, and nothing cancels it. When the PCI core starts AER
+recovery, pdsc_pci_error_detected() runs pdsc_reset_prepare() and
+recovers the device, but a pci_reset_work queued just before is left
+pending. If it runs after recovery released the device lock, it resets a
+device the driver now considers healthy, bouncing the link for no reason.
+
+Cancel pci_reset_work in pdsc_pci_error_detected() after
+pdsc_reset_prepare(), which has already stopped the health thread so it
+cannot requeue the work. cancel_work_sync() is safe under the device
+lock here because pdsc_pci_reset_thread() uses pci_try_reset_function(),
+which returns instead of blocking on the lock. Only PFs initialize
+pci_reset_work, so guard the cancel with !is_virtfn.
+
+Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread")
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260714180223.1642792-2-nikhil.rao%40amd.com?part=1
+Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260727170030.361116-1-nikhil.rao@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pds_core/main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index 71a1d4b001c22..9a2c64198d03b 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -561,7 +561,11 @@ static pci_ers_result_t pdsc_pci_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t error)
+ {
+       if (error == pci_channel_io_frozen) {
++              struct pdsc *pdsc = pci_get_drvdata(pdev);
++
+               pdsc_reset_prepare(pdev);
++              if (!pdev->is_virtfn)
++                      cancel_work_sync(&pdsc->pci_reset_work);
+               return PCI_ERS_RESULT_NEED_RESET;
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/pds_core-keep-the-health-thread-stopped-during-reset.patch b/queue-7.1/pds_core-keep-the-health-thread-stopped-during-reset.patch
new file mode 100644 (file)
index 0000000..5520c95
--- /dev/null
@@ -0,0 +1,87 @@
+From b0f915f0818741151987d71cf761bebb6e8c0239 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 16:45:48 +0000
+Subject: pds_core: keep the health thread stopped during reset
+
+From: Nikhil P. Rao <nikhil.rao@amd.com>
+
+[ Upstream commit cd09971dcc1c499ae0879010a00e9dba87abdc4f ]
+
+Commit d9407ff11809 ("pds_core: Prevent health thread from running
+during reset/remove") stops the health thread with cancel_work_sync()
+before a reset, but a devcmd timeout during pdsc_fw_down() re-queues
+health_work, so pdsc_health_thread() runs again mid-reset and double
+allocates the core DMA queues via pdsc_fw_up().
+
+Only the reset path is affected: on remove PDSC_S_STOPPING_DRIVER gates
+the health thread and the workqueue is destroyed.
+
+Use disable_work_sync() to cancel health_work and block further
+queue_work() on it, and enable_work() in pdsc_restart_health_thread() to
+re-allow it after the reset.
+
+disable_work_sync() keeps a disable depth, so every disable must be
+matched by one enable. pdsc_reset_prepare() stops the health thread and
+pdsc_reset_done() restarts it. On the AER path pdsc_pci_error_detected()
+calls pdsc_reset_prepare(), then pdsc_pci_error_resume() re-inits via
+pci_reset_function_locked() (pds_core has no .slot_reset handler), which
+runs the pair again - stopping the thread twice but restarting it once.
+Gate the disable and enable on a health_stopped flag so each fires at
+most once per stopped/running transition.
+
+Fixes: d9407ff11809 ("pds_core: Prevent health thread from running during reset/remove")
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2
+Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260727164548.359562-1-nikhil.rao@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pds_core/core.h |  1 +
+ drivers/net/ethernet/amd/pds_core/main.c | 10 ++++++++--
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h
+index 4a6b35c84dabe..2449e19321f7f 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.h
++++ b/drivers/net/ethernet/amd/pds_core/core.h
+@@ -171,6 +171,7 @@ struct pdsc {
+       struct timer_list wdtimer;
+       unsigned int wdtimer_period;
+       struct work_struct health_work;
++      bool health_stopped;
+       struct devlink_health_reporter *fw_reporter;
+       u32 fw_recoveries;
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index 8d94a4d70395e..71a1d4b001c22 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -470,8 +470,10 @@ static void pdsc_stop_health_thread(struct pdsc *pdsc)
+               return;
+       timer_shutdown_sync(&pdsc->wdtimer);
+-      if (pdsc->health_work.func)
+-              cancel_work_sync(&pdsc->health_work);
++      if (pdsc->health_work.func && !pdsc->health_stopped) {
++              disable_work_sync(&pdsc->health_work);
++              pdsc->health_stopped = true;
++      }
+ }
+ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+@@ -479,6 +481,10 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+       if (pdsc->pdev->is_virtfn)
+               return;
++      if (pdsc->health_stopped) {
++              enable_work(&pdsc->health_work);
++              pdsc->health_stopped = false;
++      }
+       timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
+       mod_timer(&pdsc->wdtimer, jiffies + 1);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch b/queue-7.1/pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch
new file mode 100644 (file)
index 0000000..d9be45a
--- /dev/null
@@ -0,0 +1,65 @@
+From b4d17a8ada124c01cd0617551f2dd4282f78b0a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jul 2026 15:35:59 +0200
+Subject: pinctrl: qcom: ipq806x: mark gpio as a GPIO pin function
+
+From: Hans Ulli Kroll <linux@ulli-kroll.de>
+
+[ Upstream commit 687f39faccba29ab26de965411db37e849af8ec2 ]
+
+The qcom pinctrl core supports marking functions that represent GPIO mode
+via PINCTRL_GPIO_PINFUNCTION(), so that strict pinmuxing does not reject
+GPIO requests for pins that are muxed to the GPIO function.
+
+Add a IPQ_GPIO_PIN_FUNCTION() helper and use it for the ipq806x gpio
+function, matching how the msm-based qcom drivers handle this.
+
+This allows ipq806x to keep the GPIO-related configuration in DTS
+without tripping over strict pinmux ownership
+checks.
+
+Fixes: cc85cb96e2e4 ("pinctrl: qcom: make the pinmuxing strict")
+Signed-off-by: Hans Ulli Kroll <linux@ulli-kroll.de>
+Acked-by: Linus Walleij <linusw@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260719134548.8830-2-linux@ulli-kroll.de
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/qcom/pinctrl-ipq8064.c | 2 +-
+ drivers/pinctrl/qcom/pinctrl-msm.h     | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+index 0a9e357e64c60..c1651f112950e 100644
+--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c
++++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+@@ -480,7 +480,7 @@ static const char * const ps_hold_groups[] = {
+ };
+ static const struct pinfunction ipq8064_functions[] = {
+-      IPQ_PIN_FUNCTION(gpio),
++      IPQ_GPIO_PIN_FUNCTION(gpio),
+       IPQ_PIN_FUNCTION(mdio),
+       IPQ_PIN_FUNCTION(ssbi),
+       IPQ_PIN_FUNCTION(spmi),
+diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
+index 4fbff61de6bb3..b94ba1a4177ed 100644
+--- a/drivers/pinctrl/qcom/pinctrl-msm.h
++++ b/drivers/pinctrl/qcom/pinctrl-msm.h
+@@ -24,6 +24,11 @@ struct pinctrl_pin_desc;
+                                       fname##_groups,         \
+                                       ARRAY_SIZE(fname##_groups))
++#define IPQ_GPIO_PIN_FUNCTION(fname)                                  \
++      [IPQ_MUX_##fname] = PINCTRL_GPIO_PINFUNCTION(#fname,            \
++                                      fname##_groups,         \
++                                      ARRAY_SIZE(fname##_groups))
++
+ #define MSM_PIN_FUNCTION(fname)                               \
+       [msm_mux_##fname] = PINCTRL_PINFUNCTION(#fname,         \
+                                       fname##_groups,         \
+-- 
+2.53.0
+
diff --git a/queue-7.1/pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch b/queue-7.1/pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch
new file mode 100644 (file)
index 0000000..17e7f1f
--- /dev/null
@@ -0,0 +1,59 @@
+From 73e15c389e891e5018de4fb0f49fdfc27e0973d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jul 2026 15:36:00 +0200
+Subject: pinctrl: qcom: ipq806x: mark pci reset as a GPIO pin function
+
+From: Hans Ulli Kroll <linux@ulli-kroll.de>
+
+[ Upstream commit fd46760956509f580f7d3d25db4de10e7c6f949b ]
+
+The qcom pinctrl core supports marking functions that represent GPIO mode
+via PINCTRL_GPIO_PINFUNCTION(), so that strict pinmuxing does not reject
+GPIO requests for pins that are muxed to the GPIO function.
+
+Mark PCIe reset as GPIO pin function
+
+This allows ipq806x to keep the PCIe-reset related configuration in DTS
+without tripping over strict pinmux ownership checks.
+
+Fixes: cc85cb96e2e4 ("pinctrl: qcom: make the pinmuxing strict")
+Signed-off-by: Hans Ulli Kroll <linux@ulli-kroll.de>
+Acked-by: Linus Walleij <linusw@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260719134548.8830-3-linux@ulli-kroll.de
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/qcom/pinctrl-ipq8064.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+index c1651f112950e..f35dbe07ab6fe 100644
+--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c
++++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+@@ -507,19 +507,19 @@ static const struct pinfunction ipq8064_functions[] = {
+       IPQ_PIN_FUNCTION(usb2_hsic),
+       IPQ_PIN_FUNCTION(rgmii2),
+       IPQ_PIN_FUNCTION(sata),
+-      IPQ_PIN_FUNCTION(pcie1_rst),
++      IPQ_GPIO_PIN_FUNCTION(pcie1_rst),
+       IPQ_PIN_FUNCTION(pcie1_prsnt),
+       IPQ_PIN_FUNCTION(pcie1_pwren_n),
+       IPQ_PIN_FUNCTION(pcie1_pwren),
+       IPQ_PIN_FUNCTION(pcie1_pwrflt),
+       IPQ_PIN_FUNCTION(pcie1_clk_req),
+-      IPQ_PIN_FUNCTION(pcie2_rst),
++      IPQ_GPIO_PIN_FUNCTION(pcie2_rst),
+       IPQ_PIN_FUNCTION(pcie2_prsnt),
+       IPQ_PIN_FUNCTION(pcie2_pwren_n),
+       IPQ_PIN_FUNCTION(pcie2_pwren),
+       IPQ_PIN_FUNCTION(pcie2_pwrflt),
+       IPQ_PIN_FUNCTION(pcie2_clk_req),
+-      IPQ_PIN_FUNCTION(pcie3_rst),
++      IPQ_GPIO_PIN_FUNCTION(pcie3_rst),
+       IPQ_PIN_FUNCTION(pcie3_prsnt),
+       IPQ_PIN_FUNCTION(pcie3_pwren_n),
+       IPQ_PIN_FUNCTION(pcie3_pwren),
+-- 
+2.53.0
+
diff --git a/queue-7.1/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch b/queue-7.1/revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
new file mode 100644 (file)
index 0000000..1a52cfe
--- /dev/null
@@ -0,0 +1,104 @@
+From 5b1f3dadd797ec074509336fe303b885d9ce408b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 12:29:48 +0000
+Subject: Revert "net: thunderbolt: Enable end-to-end flow control also in
+ transmit"
+
+From: Fan Ye <fy15309206903@gmail.com>
+
+[ Upstream commit 1881f2efbf7f78dc0a79a387b29fde6ff56d3731 ]
+
+This reverts commit a8065af3346ebd7c76ebc113451fb3ba94cf7769.
+
+Per the USB4 spec, a Transmit Descriptor Ring with E2E flow control
+disabled does not require any credits to be available before the Host
+Interface Adapter Layer transmits a tunneled packet from it. Once E2E is
+enabled on that ring the controller must first obtain end-to-end
+credits.
+
+The ASMedia ASM4242 USB4 host router (PCI 1b21:2425) never delivers
+those credits. The controller does accept the configuration: reading the
+ring OPTIONS register back right after tb_ring_start() returns exactly
+what was written, including RING_FLAG_E2E_FLOW_CONTROL (bit 28) and the
+E2E HopID field. No credit ever arrives though, so the Tx ring's
+hardware consumer index never advances and the link carries no traffic
+at all.
+
+Measured on two hosts connected point to point, onboard ASM4242 on MSI
+X870E and X870, v6.17, stock drivers/net/thunderbolt/main.c with only
+this revert applied on top:
+
+  before: 100% packet loss to the peer; thunderbolt0 is up and the
+          XDomain handshake completes ("new host found"), but iperf3
+          fails with "No route to host" once the neighbour entry
+          expires
+  after:  0% packet loss, 0.28 ms RTT; iperf3 4.21 Gb/s one way and
+          5.17 Gb/s the other (5 runs each, stddev <= 0.02), 1
+          retransmit in 10 s
+
+An instrumented build additionally showed a frozen-Tx-consumer watchdog
+firing ~30k times in a 10 s window before this change.
+
+Rx-side E2E is not touched by this revert, so peers that do return
+credits keep receive-side flow control.
+
+ASMedia does not look like an isolated case. The out-of-tree
+thunderbolt-ibverbs project disables native E2E on AMD NHI by default,
+noting that "Strix Halo has reproduced TX completion wedges with
+multiple native E2E rings active" -- the same failure mode, on a
+different vendor. Since the driver has no way to tell in advance which
+host router returns the credits, going back to the previous behaviour
+looks safer than adding a quirk per affected part; Tx-side E2E can be
+reintroduced as an opt-in for controllers that are known to implement
+the credit return.
+
+Note that the reverted commit was not fixing a reported problem, it was
+derived from the spec wording alone, so this revert is not expected to
+regress a known workload. Cc'ing the original author in case there was
+one.
+
+Fixes: a8065af3346e ("net: thunderbolt: Enable end-to-end flow control also in transmit")
+Cc: zhangjianrong <zhangjianrong5@huawei.com>
+Signed-off-by: Fan Ye <fy15309206903@gmail.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://patch.msgid.link/20260727123002.25225-1-fy15309206903@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/thunderbolt/main.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c
+index ac016890646cf..0cd98496d135d 100644
+--- a/drivers/net/thunderbolt/main.c
++++ b/drivers/net/thunderbolt/main.c
+@@ -929,12 +929,8 @@ static int tbnet_open(struct net_device *dev)
+       netif_carrier_off(dev);
+-      flags = RING_FLAG_FRAME;
+-      /* Only enable full E2E if the other end supports it too */
+-      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
+-              flags |= RING_FLAG_E2E;
+-
+-      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags);
++      ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE,
++                              RING_FLAG_FRAME);
+       if (!ring) {
+               netdev_err(dev, "failed to allocate Tx ring\n");
+               return -ENOMEM;
+@@ -953,6 +949,11 @@ static int tbnet_open(struct net_device *dev)
+       sof_mask = BIT(TBIP_PDF_FRAME_START);
+       eof_mask = BIT(TBIP_PDF_FRAME_END);
++      flags = RING_FLAG_FRAME;
++      /* Only enable full E2E if the other end supports it too */
++      if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
++              flags |= RING_FLAG_E2E;
++
+       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags,
+                               net->tx_ring.ring->hop, sof_mask,
+                               eof_mask, tbnet_start_poll, net);
+-- 
+2.53.0
+
diff --git a/queue-7.1/rqspinlock-reset-tail-when-preserving-queue-on-deadl.patch b/queue-7.1/rqspinlock-reset-tail-when-preserving-queue-on-deadl.patch
new file mode 100644 (file)
index 0000000..01cee39
--- /dev/null
@@ -0,0 +1,79 @@
+From 53d5e5122b58473e86d6f82e7025453716b89416 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Aug 2026 04:17:59 +0200
+Subject: rqspinlock: Reset tail when preserving queue on deadlock
+
+From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+
+[ Upstream commit 7a3c0289c3c8eb4607dff448ae9ff9f902c813af ]
+
+Currently, the destruction of the waiter queue is suppressed for
+rqspinlock in cases where a deadlock is detected. Deadlock checks happen
+relatively frequently (on entry for AA, within 1ms for ABBA), and waiter
+threads may not be involved in locking scenarios involving deadlocks.
+Thus, it is useful to not flush the queue and let other waiters take a
+stab at acquiring the lock after we detect a deadlock and exit.
+
+However, we need to follow the same logic as what we did previously for
+the waitq_timeout label: reset the tail, and if we cannot, signal the
+next waiter appropriately. In case of deadlocks, this signal would just
+mark the MCS node as unlocked, and in case of timeouts, it would signal
+RES_TIMEOUT_VAL. The difference thus is in the value propagated, which
+decides whether the queue remains active or gets flushed.
+
+Not doing the tail reset, and waiting for the next waiter can lead to
+cases where we are the final waiter, and thus no next waiter arrives,
+leading to intermittent stalls in this path. Once the next waiter does
+join, we will be unblocked. In the theoretical case when the next waiter
+never joins, we risk stalling indefinitely.
+
+This can only happen for ABBA deadlocks, since entry into the wait queue
+is guarded with AA checks. A precise sequence of executions leading up
+to this scenario can be:
+
+CPU 0 holds lock A.
+CPU 1 holds lock B.
+CPU 2 attempts lock B, becomes the pending waiter for B.
+CPU 0 attempts lock B. B has locked+pending bits set, thus CPU 0 queues.
+CPU 1 attempts lock A.
+CPU 0 detects an ABBA deadlock.
+
+Once deadlock detection happens for CPU 0, it will sit waiting for the
+next waiter in the queue to populate node->next, which will experience
+delays until such a waiter arrives.
+
+Fix this by adjusting the logic for the check for deadlocks preceding
+the waitq_timeout label. It would make sense to consolidate code for
+both cases and use 'ret' to distinguish the value being propagated, but
+that is left as an exercise for a future refactoring task to avoid diff
+noise in this patch.
+
+Fixes: 7bd6e5ce5be6 ("rqspinlock: Disable queue destruction for deadlocks")
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Link: https://patch.msgid.link/20260802021759.1139457-1-memxor@gmail.com
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/rqspinlock.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
+index e4e338cdb437c..2129defc4a9a7 100644
+--- a/kernel/bpf/rqspinlock.c
++++ b/kernel/bpf/rqspinlock.c
+@@ -572,9 +572,10 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
+       /* Disable queue destruction when we detect deadlocks. */
+       if (ret == -EDEADLK) {
+-              if (!next)
++              if (!try_cmpxchg_tail(lock, tail, 0)) {
+                       next = smp_cond_load_relaxed(&node->next, (VAL));
+-              arch_mcs_spin_unlock_contended(&next->locked);
++                      arch_mcs_spin_unlock_contended(&next->locked);
++              }
+               goto err_release_node;
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch b/queue-7.1/s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch
new file mode 100644 (file)
index 0000000..a92a66f
--- /dev/null
@@ -0,0 +1,91 @@
+From 23a6b7cee9620038e6028c2d6405e7551c61dfc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 15:10:43 +0200
+Subject: s390/ism: Fix UAF of sba and ieq during ism_dev_exit()
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit b1896543ce59c4258625a35cf41e23a9a1f80ea2 ]
+
+A ism interrupt handler can be active in parallel with ism_dev_exit(),
+accessing freed data structures.
+
+No new interrupts will be generated after unregister_ieq(). Drain ongoing
+interrupt handlers by free_irq(), before freeing ism data structures.
+
+Fixes: 684b89bc39ce ("s390/ism: add device driver for internal shared memory")
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260805131043.954639-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/net/ism_drv.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
+index 7d0479e4e0956..369aa21b1ff7c 100644
+--- a/drivers/s390/net/ism_drv.c
++++ b/drivers/s390/net/ism_drv.c
+@@ -148,13 +148,16 @@ static int unregister_sba(struct ism_dev *ism)
+       if (ret && ret != ISM_ERROR)
+               return -EIO;
++      return 0;
++}
++
++static void ism_free_sba(struct ism_dev *ism)
++{
+       dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
+                         ism->sba, ism->sba_dma_addr);
+       ism->sba = NULL;
+       ism->sba_dma_addr = 0;
+-
+-      return 0;
+ }
+ static int unregister_ieq(struct ism_dev *ism)
+@@ -168,13 +171,16 @@ static int unregister_ieq(struct ism_dev *ism)
+       if (ret && ret != ISM_ERROR)
+               return -EIO;
++      return 0;
++}
++
++static void ism_free_ieq(struct ism_dev *ism)
++{
+       dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
+                         ism->ieq, ism->ieq_dma_addr);
+       ism->ieq = NULL;
+       ism->ieq_dma_addr = 0;
+-
+-      return 0;
+ }
+ static int ism_read_local_gid(struct dibs_dev *dibs)
+@@ -573,6 +579,7 @@ static int ism_dev_init(struct ism_dev *ism)
+ unreg_sba:
+       unregister_sba(ism);
++      ism_free_sba(ism);
+ free_irq:
+       free_irq(pci_irq_vector(pdev, 0), ism);
+ free_vectors:
+@@ -585,9 +592,13 @@ static void ism_dev_exit(struct ism_dev *ism)
+ {
+       struct pci_dev *pdev = ism->pdev;
++      /* ism will only generate new IRQs while ieq & sba are registered */
+       unregister_ieq(ism);
+       unregister_sba(ism);
++      /* drain ongoing irpt handlers */
+       free_irq(pci_irq_vector(pdev, 0), ism);
++      ism_free_ieq(ism);
++      ism_free_sba(ism);
+       pci_free_irq_vectors(pdev);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/sched_ext-don-t-enable-non-ext-tasks-in-the-sub-sche.patch b/queue-7.1/sched_ext-don-t-enable-non-ext-tasks-in-the-sub-sche.patch
new file mode 100644 (file)
index 0000000..dae3f90
--- /dev/null
@@ -0,0 +1,78 @@
+From f99376625f6f292c30273fc82ce962304a0a98bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 10:46:04 -1000
+Subject: sched_ext: Don't enable non-ext tasks in the sub-sched task loops
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 5cdc928598095b2c7d5f265e5f21eadd1634bfbe ]
+
+Root enable and scx_post_fork() enable a task only if it's on the ext class.
+Tasks on other classes, possible under an SCX_OPS_SWITCH_PARTIAL root, are
+left READY and enabled by switching_to_scx() when they switch over. The sub
+enable-commit pass and the sub-disable re-home loop enable unconditionally,
+so a fair-class READY task in the subtree becomes ENABLED while not on
+sched_ext. A later switch to SCHED_EXT then trips the task state validation
+WARN (ENABLED with the previous state not READY) and calls ops.enable() a
+second time.
+
+Gate scx_enable_task() on the task's class in both loops.
+
+Fixes: 337ec00b1d9c ("sched_ext: Implement cgroup sub-sched enabling and disabling")
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Andrea Righi <arighi@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/ext.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
+index a8c4f665d173c..40df1be44a6d5 100644
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -5874,15 +5874,22 @@ static void scx_sub_disable(struct scx_sched *sch)
+                       /*
+                        * $p is initialized for $parent and still attached to
+                        * @sch. Disable and exit for @sch, switch over to
+-                       * $parent, override the state to READY to account for
+-                       * $p having already been initialized, and then enable.
++                       * $parent and override the state to READY to account
++                       * for $p having already been initialized.
+                        */
+                       scx_disable_and_exit_task(sch, p);
+                       scx_set_task_state(p, SCX_TASK_INIT_BEGIN);
+                       scx_set_task_state(p, SCX_TASK_INIT);
+                       scx_set_task_sched(p, parent);
+                       scx_set_task_state(p, SCX_TASK_READY);
+-                      scx_enable_task(parent, p);
++
++                      /*
++                       * A task on a non-ext class, possible under an
++                       * %SCX_OPS_SWITCH_PARTIAL root, stays READY and is
++                       * enabled by switching_to_scx() if it switches over.
++                       */
++                      if (p->sched_class == &ext_sched_class)
++                              scx_enable_task(parent, p);
+               }
+               task_rq_unlock(rq, p, &rf);
+@@ -7377,10 +7384,14 @@ static void scx_sub_enable_workfn(struct kthread_work *work)
+                       /*
+                        * $p is now only initialized for @sch and READY, which
+-                       * is what we want. Assign it to @sch and enable.
++                       * is what we want. Assign it to @sch and, if it's on
++                       * the ext class, enable. A non-ext task, possible under
++                       * an %SCX_OPS_SWITCH_PARTIAL root, stays READY and is
++                       * enabled by switching_to_scx() if it switches over.
+                        */
+                       scx_set_task_sched(p, sch);
+-                      scx_enable_task(sch, p);
++                      if (p->sched_class == &ext_sched_class)
++                              scx_enable_task(sch, p);
+                       p->scx.flags &= ~SCX_TASK_SUB_INIT;
+               }
+-- 
+2.53.0
+
diff --git a/queue-7.1/sched_ext-reject-setting-disallow-from-init_task-out.patch b/queue-7.1/sched_ext-reject-setting-disallow-from-init_task-out.patch
new file mode 100644 (file)
index 0000000..54dae46
--- /dev/null
@@ -0,0 +1,68 @@
+From e2f65dca5fd02e1bbf7843524aacc321c183a79d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 10:43:25 -1000
+Subject: sched_ext: Reject setting disallow from init_task outside the enable
+ path
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 477869bfafea65492d23de62c1b5208147c09dd2 ]
+
+The p->scx.disallow revert assumes the root enable path, where the switching
+loop reads the reverted policy right afterwards and leaves the task off SCX.
+The sub-scheduler disable path also reaches it when re-initializing the
+returned tasks on a root parent. Nothing reads the policy there: the task is
+enabled on root anyway and keeps running on the ext class with a silently
+rewritten policy.
+
+Kill the sched instead, matching the fork and non-root branches, and update
+the disallow documentation, which equated !fork with the load path and
+pointed at a stale debugfs path for nr_rejected.
+
+Fixes: 337ec00b1d9c ("sched_ext: Implement cgroup sub-sched enabling and disabling")
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Andrea Righi <arighi@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/sched/ext.h | 10 +++++-----
+ kernel/sched/ext.c        |  3 +++
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/include/linux/sched/ext.h b/include/linux/sched/ext.h
+index 2129e18ada58b..31c810a3b808b 100644
+--- a/include/linux/sched/ext.h
++++ b/include/linux/sched/ext.h
+@@ -235,11 +235,11 @@ struct sched_ext_entity {
+        * to %SCHED_EXT with -%EACCES.
+        *
+        * Can be set from ops.init_task() while the BPF scheduler is being
+-       * loaded (!scx_init_task_args->fork). If set and the task's policy is
+-       * already %SCHED_EXT, the task's policy is rejected and forcefully
+-       * reverted to %SCHED_NORMAL. The number of such events are reported
+-       * through /sys/kernel/debug/sched_ext::nr_rejected. Setting this flag
+-       * during fork is not allowed.
++       * loaded. If set and the task's policy is already %SCHED_EXT, the
++       * task's policy is rejected and forcefully reverted to %SCHED_NORMAL.
++       * The number of such events are reported through
++       * /sys/kernel/sched_ext/nr_rejected. Setting this flag from any other
++       * ops.init_task() invocation, such as during fork, fails the scheduler.
+        */
+       bool                    disallow;       /* reject switching into SCX */
+diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
+index 5c780756e3623..6904d65d2b852 100644
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -3581,6 +3581,9 @@ static int __scx_init_task(struct scx_sched *sch, struct task_struct *p, bool fo
+               } else if (unlikely(fork)) {
+                       scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] during fork",
+                                 p->comm, p->pid);
++              } else if (unlikely(scx_enable_state() != SCX_ENABLING)) {
++                      scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] outside the enable path",
++                                p->comm, p->pid);
+               } else {
+                       struct rq *rq;
+                       struct rq_flags rf;
+-- 
+2.53.0
+
diff --git a/queue-7.1/sched_ext-skip-sub-disable-teardown-for-never-linked.patch b/queue-7.1/sched_ext-skip-sub-disable-teardown-for-never-linked.patch
new file mode 100644 (file)
index 0000000..96c651d
--- /dev/null
@@ -0,0 +1,77 @@
+From f73aa863b764f0a96a9ccb1709bb7972990be1ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 10:45:23 -1000
+Subject: sched_ext: Skip sub-disable teardown for never-linked sub-schedulers
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 8c13364db9c9a43ed286f3a8d0fb9477b1adc43c ]
+
+A sub-scheduler enable can fail before scx_link_sched() links the sched into
+the hierarchy, e.g. when the parent is already being disabled, and cleanup
+still runs the full scx_sub_disable().
+
+That is racy against root disable: drain_descendants() is the only ordering
+between a sub's disable-time task walk and root disable's all-task teardown,
+and an unlinked sub is invisible to it. Root's teardown can thus run between
+the never-linked sub's drain and its walk, exiting every task to no
+scheduler.
+
+The walk then trips the membership WARN and re-homes the exited tasks onto
+the dying hierarchy, a use-after-free.
+
+Skip the cgroup ownership reset and the task walk if @sch was never linked,
+indicated by the empty ->sibling as unlinking only happens later in the same
+function. The membership WARN remains valid: a linked sub is always waited
+on by an ancestor's drain.
+
+Fixes: 337ec00b1d9c ("sched_ext: Implement cgroup sub-sched enabling and disabling")
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Andrea Righi <arighi@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/ext.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
+index 6904d65d2b852..a8c4f665d173c 100644
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -5798,6 +5798,15 @@ static void scx_sub_disable(struct scx_sched *sch)
+       percpu_down_write(&scx_fork_rwsem);
+       scx_cgroup_lock();
++      /*
++       * An enable that failed before scx_link_sched() never owned a cgroup or
++       * task and won't be waited on by an ancestor's drain_descendants().
++       * Nothing to reparent and walking the tasks can misbehave as the task
++       * ownership invariant (either owned by self or parent) does not hold.
++       */
++      if (list_empty(&sch->sibling))
++              goto dump;
++
+       set_cgroup_sched(sch_cgroup(sch), parent);
+       scx_task_iter_start(&sti, sch->cgrp);
+@@ -5810,8 +5819,8 @@ static void scx_sub_disable(struct scx_sched *sch)
+                       continue;
+               /*
+-               * By the time control reaches here, all descendant schedulers
+-               * should already have been disabled.
++               * By the time control reaches here, all linked descendant
++               * schedulers should have been disabled.
+                */
+               WARN_ON_ONCE(!scx_task_on_sched(sch, p));
+@@ -5881,6 +5890,7 @@ static void scx_sub_disable(struct scx_sched *sch)
+       }
+       scx_task_iter_stop(&sti);
++dump:
+       scx_disable_dump(sch);
+       scx_cgroup_unlock();
+-- 
+2.53.0
+
diff --git a/queue-7.1/sctp-clear-control-chunk-transport-if-it-is-being-re.patch b/queue-7.1/sctp-clear-control-chunk-transport-if-it-is-being-re.patch
new file mode 100644 (file)
index 0000000..a77d292
--- /dev/null
@@ -0,0 +1,54 @@
+From 27081d1fb3c26192eb545857097e8b348148766d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 11:18:40 -0400
+Subject: sctp: clear control chunk transport if it is being removed
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit c9158ceaf27780ef64534ad72f44ffde3f8ccc49 ]
+
+sctp_make_heartbeat_ack() caches the destination transport in
+chunk->transport without taking a reference. When src_out_of_asoc_ok is
+enabled, the HEARTBEAT ACK may remain queued on control_chunk_list instead
+of being transmitted immediately.
+
+If the peer transport is removed while the chunk is still queued,
+sctp_assoc_rm_peer() drops the transport and schedules it for RCU freeing,
+but only clears cached transport pointers in out_chunk_list.  The queued
+control chunk therefore retains a dangling transport pointer.
+
+Once an ASCONF_ACK clears the suppression and the queued control chunk is
+transmitted, SCTP dereferences the stale transport pointer, leading to a
+use-after-free.
+
+Fix this by also clearing chunk->transport for queued control chunks in
+control_chunk_list when removing the transport.
+
+Fixes: 8a07eb0a50ae ("sctp: Add ASCONF operation on the single-homed host")
+Reported-by: Daniele Linguaglossa <danielelinguaglossa@gmail.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/7e1168cb722132152a29d47e5eafaeac4a3bf6f3.1785943120.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/associola.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index b6ac0966420a1..5b0ae616e1ff9 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -573,6 +573,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
+               if (ch->transport == peer)
+                       ch->transport = NULL;
++      list_for_each_entry(ch, &asoc->outqueue.control_chunk_list, list)
++              if (ch->transport == peer)
++                      ch->transport = NULL;
++
+       asoc->peer.transport_count--;
+       sctp_ulpevent_notify_peer_addr_change(peer, SCTP_ADDR_REMOVED, 0);
+-- 
+2.53.0
+
diff --git a/queue-7.1/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch b/queue-7.1/sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
new file mode 100644 (file)
index 0000000..0b60070
--- /dev/null
@@ -0,0 +1,57 @@
+From 25c5edb238d768d240ce7d4f4fb15a63b5b4f4c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 10:55:14 +0800
+Subject: sctp: fix addip_serial increment on ASCONF_ACK allocation failure
+
+From: Qing Luo <luoqing@kylinos.cn>
+
+[ Upstream commit aa2e13ae8d3cbe2c15ef4f7e971b2de0832794aa ]
+
+In sctp_process_asconf(), when sctp_make_asconf_ack() fails to allocate
+the ASCONF_ACK chunk due to memory pressure, the code jumps to the
+done label where asoc->peer.addip_serial is unconditionally incremented.
+
+This leaves the peer's ASCONF (serial N) unacknowledged while the local
+endpoint now expects serial N+1. When the peer retransmits serial N, it
+falls into the serial < addip_serial + 1 branch ,
+which attempts to look up a cached ACK for serial N. No cached ACK
+exists since the allocation failed, so the retransmission is silently
+discarded. The peer eventually times out and ABORTs the association.
+
+Move the addip_serial increment inside the if (asconf_ack) block so that
+the serial number is only advanced when the ASCONF_ACK is successfully
+created and cached. This way, on allocation failure, the serial number
+is unchanged and the peer's retransmitted ASCONF will be correctly
+re-processed.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Qing Luo <luoqing@kylinos.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260804025514.241767-1-l1138897701@163.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 0ae30c3c8913a..e25612e9d0821 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -3336,12 +3336,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+                       goto done;
+       }
+ done:
+-      asoc->peer.addip_serial++;
+-
+       /* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+        * after freeing the reference to old asconf ack if any.
+        */
+       if (asconf_ack) {
++              asoc->peer.addip_serial++;
+               sctp_chunk_hold(asconf_ack);
+               list_add_tail(&asconf_ack->transmitted_list,
+                             &asoc->asconf_ack_list);
+-- 
+2.53.0
+
diff --git a/queue-7.1/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch b/queue-7.1/selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
new file mode 100644 (file)
index 0000000..5802e90
--- /dev/null
@@ -0,0 +1,88 @@
+From e7fb5a399860559dfdf9e848b54219e4f3db6ecd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2026 21:46:35 +0200
+Subject: selftests/ftrace: refactor eprobes test to fix argument checks
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+[ Upstream commit 6e3abef2a27e7402a94111c9eff85d887e64a309 ]
+
+The add/remove eprobe test installs an eprobe for the openat syscall and
+runs ls. It checks the filenames that were opened by ls against a
+whitelist and a blacklist.
+
+Commit 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING
+pointer") fixed access to some string fields in eprobes. This triggers
+test failures as the blacklist does not allow relative paths for the
+openat parameters.
+
+What makes this test unstable is the fact that the openat calls vary a
+lot between different systems.
+
+Refactor the test to make it more robust. "cd <directory>" will issue a
+chdir syscall with the target directory as parameter. Set an eprobe on
+the sys_enter_chdir event and filter for the exact directory name. Allow
+(fault) as fallback.
+
+Link: https://lore.kernel.org/all/20260804194705.760893-1-martin@kaiser.cx/
+
+Fixes: 206b25c09080 ("tracing: eprobe: read the complete FILTER_PTR_STRING pointer")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202607151010.b68428e1-lkp@intel.com
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ftrace/test.d/dynevent/add_remove_eprobe.tc  | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+index c300eb0202620..e2322693d0c32 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
+@@ -1,16 +1,16 @@
+ #!/bin/sh
+ # SPDX-License-Identifier: GPL-2.0
+ # description: Generic dynamic event - add/remove eprobe events
+-# requires: dynamic_events events/syscalls/sys_enter_openat "<attached-group>.<attached-event> [<args>]":README
++# requires: dynamic_events events/syscalls/sys_enter_chdir "<attached-group>.<attached-event> [<args>]":README
+ echo 0 > events/enable
+ clear_dynamic_events
+ SYSTEM="syscalls"
+-EVENT="sys_enter_openat"
++EVENT="sys_enter_chdir"
+ FIELD="filename"
+-EPROBE="eprobe_open"
++EPROBE="eprobe_chdir"
+ OPTIONS="file=+0(\$filename):ustring"
+ echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events
+@@ -18,20 +18,14 @@ grep -q "$EPROBE" dynamic_events
+ test -d events/eprobes/$EPROBE
+ echo 1 > events/eprobes/$EPROBE/enable
+-ls
++cd /sys/kernel/tracing
+ echo 0 > events/eprobes/$EPROBE/enable
+-content=`grep '^ *ls-' trace | grep 'file='`
+-nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."' -e '(fault)' ` || true
+-
++content=`grep -e 'file="/sys/kernel/tracing"\|(fault)' trace`
+ if [ -z "$content" ]; then
+       exit_fail
+ fi
+-if [ ! -z "$nocontent" ]; then
+-      exit_fail
+-fi
+-
+ echo "-:$EPROBE" >> dynamic_events
+ ! grep -q "$EPROBE" dynamic_events
+-- 
+2.53.0
+
diff --git a/queue-7.1/selftests-sched_ext-handle-sleeping-task-affinity-ch.patch b/queue-7.1/selftests-sched_ext-handle-sleeping-task-affinity-ch.patch
new file mode 100644 (file)
index 0000000..b62b276
--- /dev/null
@@ -0,0 +1,81 @@
+From 0ada57190ae36b4a2ed98f85d13d52fbe4c085f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 09:59:55 +0000
+Subject: selftests/sched_ext: Handle sleeping task affinity changes in numa
+ test
+
+From: Kuba Piecuch <jpiecuch@google.com>
+
+[ Upstream commit d4a00d61a5c2c24973175ace5368d1f6acf9bb0a ]
+
+When a sleeping task's affinity is changed, task_cpu(p) can be outside
+of p->cpus_ptr until after select_task_rq() selects a new runqueue for
+the task during wakeup.
+
+Thus, the task's NUMA node determined by numa_select_cpu() can be
+completely outside of the task's cpumask, leading to
+scx_pick_{idle,any}_cpu_node() failing to find an eligible CPU and
+returning -EBUSY. This leads to the numa.bpf.c scheduler abnormally
+exiting with the following message in dmesg:
+
+sched_ext: numa: invalid CPU -16
+   scx_bpf_cpu_node+0x120/0x190
+   bpf_prog_0a34b8e0f515771f_numa_select_cpu+0x108/0x14e
+   bpf__sched_ext_ops_select_cpu+0x4f/0xb4
+   select_task_rq_scx+0xb0/0x210
+   select_task_rq+0xa0/0xd0
+   __try_to_wake_up+0x196/0x650
+   complete_all+0x76/0x100
+   migration_cpu_stop+0x22b/0x300
+   cpu_stopper_thread+0xc1/0x180
+   smpboot_thread_fn+0x16b/0x230
+   kthread+0x2d7/0x350
+   ret_from_fork+0x1c2/0x350
+   ret_from_fork_asm+0x1a/0x30
+
+Make numa_select_cpu() robust against this case by returning @prev_cpu
+if no CPU could be found in the selected NUMA node _and_ we have reason
+to believe that the task's affinity was changed while it was sleeping.
+
+Fixes: 5ae5161820e5 ("selftests/sched_ext: Add NUMA-aware scheduler test")
+Signed-off-by: Kuba Piecuch <jpiecuch@google.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/sched_ext/numa.bpf.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/sched_ext/numa.bpf.c b/tools/testing/selftests/sched_ext/numa.bpf.c
+index 78cc49a7f9a67..6b4515c28aa0b 100644
+--- a/tools/testing/selftests/sched_ext/numa.bpf.c
++++ b/tools/testing/selftests/sched_ext/numa.bpf.c
+@@ -34,7 +34,8 @@ static bool is_cpu_idle(s32 cpu, int node)
+ s32 BPF_STRUCT_OPS(numa_select_cpu,
+                  struct task_struct *p, s32 prev_cpu, u64 wake_flags)
+ {
+-      int node = __COMPAT_scx_bpf_cpu_node(scx_bpf_task_cpu(p));
++      s32 task_cpu = scx_bpf_task_cpu(p);
++      int node = __COMPAT_scx_bpf_cpu_node(task_cpu);
+       s32 cpu;
+       /*
+@@ -48,6 +49,16 @@ s32 BPF_STRUCT_OPS(numa_select_cpu,
+               cpu = __COMPAT_scx_bpf_pick_any_cpu_node(p->cpus_ptr, node,
+                                               __COMPAT_SCX_PICK_IDLE_IN_NODE);
++      /*
++       * @task_cpu may be outside of p->cpus_ptr if @p's affinity
++       * changed while it was sleeping. This means it's possible for
++       * p->cpus_ptr to not include any CPUs from @node.
++       * If we failed to find a cpu in @node, check if @task_cpu
++       * is outside of p->cpus_ptr and just return @prev_cpu if it is.
++       */
++      if (cpu < 0 && !bpf_cpumask_test_cpu(task_cpu, p->cpus_ptr))
++              return prev_cpu;
++
+       if (is_cpu_idle(cpu, node))
+               scx_bpf_error("CPU %d should be marked as busy", cpu);
+-- 
+2.53.0
+
index e69ca3316b034029fa02c78878c3dfebc5b9bd02..3cd5226c02bc940ec0752ca087fe11dd71f38a6f 100644 (file)
@@ -4,3 +4,122 @@ selftests-bpf-add-tests-for-sleepable-tracepoint-pro.patch
 gpio-pca953x-fix-pca953x_irq_bus_sync_unlock-regmap-.patch
 drm-amd-display-add-av-mute-wait-frames-to-dce110_se.patch
 drm-amd-display-check-for-tg-ops-in-dce110_set_avmut.patch
+arm64-dts-qcom-glymur-fix-pcie-smmu-interrupts.patch
+arm64-dts-qcom-glymur-fix-qup-serial-engine-irqs.patch
+arm64-dts-qcom-purwa-fix-gpu-iommu-property.patch
+arm64-dts-qcom-monaco-add-default-gic-address-cells.patch
+arm64-dts-qcom-sm8650-fix-ipa-imem-slice.patch
+arm64-dts-qcom-sdm850-lenovo-yoga-c630-lower-psci-cl.patch
+sched_ext-reject-setting-disallow-from-init_task-out.patch
+sched_ext-skip-sub-disable-teardown-for-never-linked.patch
+sched_ext-don-t-enable-non-ext-tasks-in-the-sub-sche.patch
+nfs-pin-the-struct-nfs_server-during-a-free_stateid-.patch
+nfs-decrement-refcounts-if-allocating-nfs_free_state.patch
+arm64-dts-broadcom-bcm2712-remove-non-functional-el2.patch
+soc-aspeed-lpc-snoop-fix-usercopy-overflow-in-snoop_.patch
+xfs-handle-null-b_addr-in-xfs_buf_free.patch
+arm-npcm-fix-of-node-refcount-leaks-in-smp-setup.patch
+selftests-sched_ext-handle-sleeping-task-affinity-ch.patch
+pinctrl-qcom-ipq806x-mark-gpio-as-a-gpio-pin-functio.patch
+pinctrl-qcom-ipq806x-mark-pci-reset-as-a-gpio-pin-fu.patch
+ovpn-add-missing-rtnl_link_ops-get_size-callback.patch
+arm-dts-bcm5301x-fix-pcie-controller-2-second-interr.patch
+ovpn-skip-rehash-for-peers-already-removed-from-by_i.patch
+ovpn-rehash-peer-in-by_transp_addr-table-on-cmd_peer.patch
+ovpn-ensure-socket-is-owned-by-ovpn-before-deref-sk_.patch
+ovpn-zero-initialize-sockaddr-before-learning-a-floa.patch
+ovpn-hash-floated-peer-by-transport-identity-only.patch
+ovpn-disable-ipv4-redirects-on-mp-interfaces.patch
+ovpn-ensure-tcp-vars-are-initialized-first.patch
+ovpn-fix-incorrect-use-of-rcu_access_pointer.patch
+drm-bridge-ps8640-propagate-aux-transfer-register-er.patch
+net-hns3-fix-speed-configuration-residue-after-drive.patch
+revert-net-thunderbolt-enable-end-to-end-flow-contro.patch
+bonding-alb-re-check-primary_is_promisc-under-rtnl-i.patch
+enic-fix-tx_hang_reset-use-after-free-on-device-remo.patch
+net-mlx5e-tc-check-if-flow-is-peer-before-acquiring-.patch
+pds_core-keep-the-health-thread-stopped-during-reset.patch
+pds_core-cancel-pending-pci-reset-work-on-aer-recove.patch
+netfilter-ipset-switch-ext_size-to-atomic64_t.patch
+ipvs-avoid-out-of-bounds-write-in-ip_vs_nat_icmp.patch
+ipvs-return-the-csum-validation-for-forward-hook.patch
+watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch
+btrfs-lzo-add-error-message-for-invalid-headers.patch
+btrfs-lzo-reject-inline-extents-without-valid-header.patch
+btrfs-fix-memory-leak-in-btrfs_do_encoded_write.patch
+btrfs-move-large-data-folios-out-of-experimental-fea.patch
+btrfs-disable-bs-ps-support-if-no-transparent-hugepa.patch
+btrfs-initialize-inode-mapping-flags-for-cached-inod.patch
+accel-amxdna-fix-page-insertion-errors-in-amdxdna_in.patch
+bpf-preserve-pointer-state-for-commuted-arithmetic.patch
+bpf-propagate-untrusted-pointer-state-in-commuted-ar.patch
+net-smc-fix-qentry-overwrite-for-confirm_link-and-ad.patch
+net-sched-cls_route-fix-fastmap-use-after-free-on-fi.patch
+net-hisilicon-hix5hd2_gmac-remove-redundant-napi-del.patch
+devlink-fix-net-namespace-reference-leak-in-reload.patch
+net-mlx5-fw_tracer-return-null-on-create-error.patch
+accel-amdxdna-fix-locally-exploitable-bug_on-in-amdx.patch
+bpf-fix-netns-reference-imbalance-in-conntrack-kfunc.patch
+counter-microchip-tcb-capture-fix-dt-channel-validat.patch
+bpf-tcp-fix-use-after-free-in-bpf_iter_tcp_establish.patch
+alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken.patch
+alsa-usb-audio-add-quirk_flag_mixer_get_cur_broken-f.patch
+vhost_iotlb-bound-map-allocation-in-add_range.patch
+vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
+vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch
+hwmon-pmbus-core-avoid-race-condition-during-probe.patch
+hwmon-pmbus-fix-type-confusion-in-notification-logic.patch
+tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
+bnxt-fix-memory-leak-in-bnxt_queue_mem_alloc-error-c.patch
+xsk-require-at-least-16-bytes-of-tx-metadata.patch
+xsk-pass-tx-metadata-pointer-by-reference.patch
+xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch
+xsk-validate-launch-time-metadata-size.patch
+xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch
+xsk-validate-metadata-when-processing-requests.patch
+bnge-fix-null-pointer-dereference-in-aux-device-rele.patch
+udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
+net-sched-sch_cake-drop-warn_on-1-for-malformed-pack.patch
+vhost-scsi-validate-t10-pi-scatterlist-counts.patch
+vhost-scsi-reject-feature-changes-after-endpoint.patch
+net-openvswitch-check-ethernet-header-length-in-key_.patch
+net-sched-cls_api-always-acquire-rtnl_lock-when-dest.patch
+drm-xe-fix-memory-leak-in-exec_queue_set_hang_replay.patch
+drm-xe-uc-apply-rcs-ccs-yield-policy-to-sr-iov-vfs.patch
+hwmon-nzxt-smart2-check-return-value-of-init_device-.patch
+hwmon-pmbus-lm25066-fix-pmbus-coefficient-calculatio.patch
+selftests-ftrace-refactor-eprobes-test-to-fix-argume.patch
+net-stmmac-resume-phy-before-hardware-setup-when-ope.patch
+bnge-use-int-for-bnge_fix_rings_count-return-value.patch
+net-mlx5e-fix-bql-reset-on-sq-re-activation.patch
+bnxt_en-move-rss-table-fill-outside-__bnxt_hwrm_vnic.patch
+bnxt_en-determine-and-store-default-rx-ring-in-vnic-.patch
+bnxt_en-refresh-vnic-default-ring-on-queue-restart-i.patch
+bnxt_en-disable-eop-for-tpa-on-all-chips-to-prevent-.patch
+bnxt_en-fix-ptp-pps-setting-bug.patch
+sctp-fix-addip_serial-increment-on-asconf_ack-alloca.patch
+bpf-check-sk_state-before-sk_protocol-in-bpf_tcp_-_s.patch
+tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
+netfilter-nf_flow_table-drop-existing-skb-dst-before.patch
+net-ncsi-fix-heap-oob-read-in-ncsi_cmd_send_cmd-payl.patch
+net-prestera-validate-firmware-header-length.patch
+net-remove-warn_on_once-from-sk_mc_loop.patch
+net-smc-fix-toctou-race-between-smc_listen_out-and-l.patch
+net-qrtr-ns-raise-lookup-limit-to-128.patch
+net-thunderbolt-tear-down-dma-paths-before-stopping-.patch
+ata-pata_sl82c105-fix-bridge-revision-use-after-free.patch
+bnge-fix-resource-leak-in-bnge_init_nic-error-path.patch
+s390-ism-fix-uaf-of-sba-and-ieq-during-ism_dev_exit.patch
+net-atm-fix-slab-out-of-bounds-read-in-vcc_setsockop.patch
+sctp-clear-control-chunk-transport-if-it-is-being-re.patch
+tls-don-t-abort-the-connection-on-signal-interrupted.patch
+watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch
+rqspinlock-reset-tail-when-preserving-queue-on-deadl.patch
+hwmon-corsair-psu-fix-possible-out-of-bounds-access-.patch
+hwmon-ads7828-fix-external-vref-regulator-handling.patch
+hwmon-ltc4282-avoid-overflow-in-maximum-power-calcul.patch
+hwmon-ltc4282-clamp-negative-current-limits.patch
+hwmon-ltc4282-fix-parsing-adi-current-limit-sense-mi.patch
+hwmon-support-guard-and-scoped_guard-for-subsystem-l.patch
+hwmon-corsair-psu-serialize-debugfs-access-against-h.patch
+alsa-usb-audio-fix-sticky-mixer-regressions-on-m-aud.patch
diff --git a/queue-7.1/soc-aspeed-lpc-snoop-fix-usercopy-overflow-in-snoop_.patch b/queue-7.1/soc-aspeed-lpc-snoop-fix-usercopy-overflow-in-snoop_.patch
new file mode 100644 (file)
index 0000000..7ab45ad
--- /dev/null
@@ -0,0 +1,139 @@
+From 893957595ada0b0557f3cb1fde74cfe8764e6041 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jun 2026 19:07:43 +0000
+Subject: soc: aspeed: lpc-snoop: Fix usercopy overflow in snoop_file_read
+
+From: Karthikeyan KS <karthiproffesional@gmail.com>
+
+[ Upstream commit 1acef6d85bfd98bd9dfe1f08bffa397a4dda8a6f ]
+
+put_fifo_with_discard() acts as both producer and consumer on the kfifo:
+it calls kfifo_skip() (advances out) and kfifo_put() (advances in) from
+the IRQ handler without synchronizing with snoop_file_read(), which also
+consumes via kfifo_to_user(). On SMP systems this concurrent access can
+leave (in - out) larger than the ring buffer, so __kfifo_to_user()'s clamp
+to (in - out) is ineffective and kfifo_copy_to_user() can attempt a
+copy_to_user() past the kmalloc-2k backing store:
+
+  usercopy: Kernel memory exposure attempt detected from SLUB object
+  'kmalloc-2k' (offset 0, size 2049)!
+  kernel BUG at mm/usercopy.c!
+  Call trace:
+   usercopy_abort
+   __check_heap_object
+   __check_object_size
+   kfifo_copy_to_user
+   __kfifo_to_user
+   snoop_file_read
+   vfs_read
+
+Serialize kfifo access with a per-channel spinlock shared between the
+IRQ handler (producer) and the file reader (consumer).  Annotate @fifo
+with __guarded_by(&lock) and opt the driver into context analysis so the
+compiler enforces that all fifo access holds the lock.
+
+Fixes: 3772e5da4454 ("drivers/misc: Aspeed LPC snoop output using misc chardev")
+Signed-off-by: Karthikeyan KS <karthiproffesional@gmail.com>
+Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/aspeed/Makefile           |  1 +
+ drivers/soc/aspeed/aspeed-lpc-snoop.c | 38 ++++++++++++++++++---------
+ 2 files changed, 27 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
+index b35d745929646..b5188dcde37a7 100644
+--- a/drivers/soc/aspeed/Makefile
++++ b/drivers/soc/aspeed/Makefile
+@@ -4,3 +4,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP)         += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_UART_ROUTING)     += aspeed-uart-routing.o
+ obj-$(CONFIG_ASPEED_P2A_CTRL)         += aspeed-p2a-ctrl.o
+ obj-$(CONFIG_ASPEED_SOCINFO)          += aspeed-socinfo.o
++CONTEXT_ANALYSIS_aspeed-lpc-snoop.o   := y
+diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c
+index b03310c0830d2..7fa1a345acacc 100644
+--- a/drivers/soc/aspeed/aspeed-lpc-snoop.c
++++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c
+@@ -11,6 +11,7 @@
+  */
+ #include <linux/bitops.h>
++#include <linux/cleanup.h>
+ #include <linux/clk.h>
+ #include <linux/dev_printk.h>
+ #include <linux/interrupt.h>
+@@ -74,7 +75,8 @@ struct aspeed_lpc_snoop_channel_cfg {
+ struct aspeed_lpc_snoop_channel {
+       const struct aspeed_lpc_snoop_channel_cfg *cfg;
+       bool enabled;
+-      struct kfifo            fifo;
++      spinlock_t              lock;
++      struct kfifo            fifo __guarded_by(&lock);
+       wait_queue_head_t       wq;
+       struct miscdevice       miscdev;
+ };
+@@ -114,6 +116,7 @@ static ssize_t snoop_file_read(struct file *file, char __user *buffer,
+                               size_t count, loff_t *ppos)
+ {
+       struct aspeed_lpc_snoop_channel *chan = snoop_file_to_chan(file);
++      u8 *buf __free(kfree) = NULL;
+       unsigned int copied;
+       int ret = 0;
+@@ -125,9 +128,16 @@ static ssize_t snoop_file_read(struct file *file, char __user *buffer,
+               if (ret == -ERESTARTSYS)
+                       return -EINTR;
+       }
+-      ret = kfifo_to_user(&chan->fifo, buffer, count, &copied);
+-      if (ret)
+-              return ret;
++
++      count = min_t(size_t, count, SNOOP_FIFO_SIZE);
++
++      buf = kmalloc(count, GFP_KERNEL);
++      if (!buf)
++              return -ENOMEM;
++
++      copied = kfifo_out_spinlocked(&chan->fifo, buf, count, &chan->lock);
++      if (copied && copy_to_user(buffer, buf, copied))
++              return -EFAULT;
+       return copied;
+ }
+@@ -151,11 +161,13 @@ static const struct file_operations snoop_fops = {
+ /* Save a byte to a FIFO and discard the oldest byte if FIFO is full */
+ static void put_fifo_with_discard(struct aspeed_lpc_snoop_channel *chan, u8 val)
+ {
+-      if (!kfifo_initialized(&chan->fifo))
+-              return;
+-      if (kfifo_is_full(&chan->fifo))
+-              kfifo_skip(&chan->fifo);
+-      kfifo_put(&chan->fifo, val);
++      scoped_guard(spinlock, &chan->lock) {
++              if (!kfifo_initialized(&chan->fifo))
++                      return;
++              if (kfifo_is_full(&chan->fifo))
++                      kfifo_skip(&chan->fifo);
++              kfifo_put(&chan->fifo, val);
++      }
+       wake_up_interruptible(&chan->wq);
+ }
+@@ -239,9 +251,11 @@ static int aspeed_lpc_enable_snoop(struct device *dev,
+       if (!channel->miscdev.name)
+               return -ENOMEM;
+-      rc = kfifo_alloc(&channel->fifo, SNOOP_FIFO_SIZE, GFP_KERNEL);
+-      if (rc)
+-              return rc;
++      scoped_guard(spinlock_init, &channel->lock) {
++              rc = kfifo_alloc(&channel->fifo, SNOOP_FIFO_SIZE, GFP_KERNEL);
++              if (rc)
++                      return rc;
++      }
+       rc = misc_register(&channel->miscdev);
+       if (rc)
+-- 
+2.53.0
+
diff --git a/queue-7.1/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch b/queue-7.1/tcp-do-not-change-rcv_ssthresh-in-tcp_measure_rcv_ms.patch
new file mode 100644 (file)
index 0000000..4b146cc
--- /dev/null
@@ -0,0 +1,61 @@
+From c0319886e76a9d831c14a9f2b602e99046babf0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2026 20:08:06 -0700
+Subject: tcp: do not change rcv_ssthresh in tcp_measure_rcv_mss()
+
+From: Nathan Gao <zcgao@amazon.com>
+
+[ Upstream commit 0e125ecfe20c077625cf0be8d750d5c3abc0dce9 ]
+
+Commit f5da7c45188e ("tcp: adjust rcvq_space after updating scaling
+ratio") replaced the direct window_clamp update in tcp_measure_rcv_mss()
+with a call to tcp_set_window_clamp(), a helper that implements the
+TCP_WINDOW_CLAMP setsockopt. As a side effect, the helper also shrinks
+rcv_ssthresh via __tcp_adjust_rcv_ssthresh().
+
+As a result, each scaling_ratio decrease detected by
+tcp_measure_rcv_mss() also cuts rcv_ssthresh. Elsewhere in TCP,
+rcv_ssthresh is usually cut under memory pressure and grows via
+tcp_grow_window().
+
+Flows whose segment sizes vary keep scaling_ratio oscillating, which
+leads to an unstable rcv_ssthresh: a dip of rcv_ssthresh only recovers
+via tcp_grow_window(), keeping the advertised window at a relatively
+low level even after the ratio itself has recovered, and can even stall
+the sender.
+
+Observed on a customer's proxy gateway after upgrading from kernel 6.1
+to 6.12: in the worst case, rcv_ssthresh was cut in half by a
+scaling_ratio dip. P99 latency jumped from <10ms on 6.1 to ~100ms on
+6.12, and almost returned to the 6.1 level with this patch applied.
+
+Restore the plain WRITE_ONCE() update of window_clamp, as introduced
+in commit a2cbb1603943 ("tcp: Update window clamping condition"), and
+keep the rcvq_space.space adjustment. Now rcv_ssthresh is decoupled from
+scaling_ratio changes in tcp_measure_rcv_mss().
+
+Fixes: f5da7c45188e ("tcp: adjust rcvq_space after updating scaling ratio")
+Signed-off-by: Nathan Gao <zcgao@amazon.com>
+Link: https://patch.msgid.link/20260725030806.28135-1-zcgao@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index eed808c2adbb5..e2c022f02c644 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -252,7 +252,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
+                               struct tcp_sock *tp = tcp_sk(sk);
+                               val = tcp_win_from_space(sk, sk->sk_rcvbuf);
+-                              tcp_set_window_clamp(sk, val);
++                              WRITE_ONCE(tp->window_clamp, val);
+                               if (tp->window_clamp < tp->rcvq_space.space)
+                                       tp->rcvq_space.space = tp->window_clamp;
+-- 
+2.53.0
+
diff --git a/queue-7.1/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch b/queue-7.1/tcp-fix-tfo-max_qlen-accounting-across-reuseport-mig.patch
new file mode 100644 (file)
index 0000000..57a8879
--- /dev/null
@@ -0,0 +1,72 @@
+From f3ba535f5118933506bcc2198a4dc0d2286eb1a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Aug 2026 14:17:38 +0800
+Subject: tcp: fix TFO max_qlen accounting across reuseport migration
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit a0ab2ba83e35159d81cec830a92e885ecf8139be ]
+
+A listener's TCP_FASTOPEN max_qlen stops being accurate and lets through
+far more pending Fast Open requests than it was configured for.
+
+This only shows up with SO_REUSEPORT listener migration, where closing a
+listener hands its still-pending TFO children over to a surviving one.
+
+fastopenq.qlen is charged in tcp_fastopen_create_child() when the child
+is created and uncharged in reqsk_fastopen_remove() when the handshake
+completes.  The uncharge follows rsk_listener of the request the child
+points at, and inet_reqsk_clone() has repointed the child at a new
+request owned by the new listener, so the ++ and the -- land on two
+different sockets.  The new listener's qlen drifts negative and its
+limit no longer binds.
+
+Charge the new listener during migration, like reqsk_queue_migrated()
+already does for queue->young and queue->qlen.
+
+Fixes: 54b92e841937 ("tcp: Migrate TCP_ESTABLISHED/TCP_SYN_RECV sockets in accept queues.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260803061739.134737-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index 690f7fb3f029e..935b46db61541 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -946,11 +946,23 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
+       nreq->rsk_listener = sk;
+-      /* We need not acquire fastopenq->lock
+-       * because the child socket is locked in inet_csk_listen_stop().
+-       */
+-      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
++      if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener) {
++              struct fastopen_queue *fastopenq;
++
++              /* reqsk_fastopen_remove() will uncharge nreq->rsk_listener,
++               * that is @sk, so charge it here.  Unlike the listener
++               * being closed, @sk is live and needs its lock.
++               */
++              fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
++              spin_lock_bh(&fastopenq->lock);
++              fastopenq->qlen++;
++              spin_unlock_bh(&fastopenq->lock);
++
++              /* We need not acquire fastopenq->lock
++               * because the child socket is locked in inet_csk_listen_stop().
++               */
+               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
++      }
+       return nreq;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/tls-don-t-abort-the-connection-on-signal-interrupted.patch b/queue-7.1/tls-don-t-abort-the-connection-on-signal-interrupted.patch
new file mode 100644 (file)
index 0000000..5770e88
--- /dev/null
@@ -0,0 +1,45 @@
+From 9d0a48e0d834347f3e32ec1af19476bdf8ed47e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Aug 2026 08:22:48 +0200
+Subject: tls: don't abort the connection on signal-interrupted sends
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+[ Upstream commit af0e5cdd031f4f4a8f6d4160bfbda4f36872b0ed ]
+
+When a signal interrupts a blocking send, tls_tx_records() treats the
+resulting -ERESTARTSYS as a transmission failure and marks the socket
+errored via tls_err_abort() with the raw error code. Later syscalls
+return the kernel-internal errno 512 (ERESTARTSYS) to userspace, as the
+signal it stems from is no longer pending during syscall exit and thus
+never translated.
+
+An interrupted send is not a connection error: the partially sent record
+stays queued and is resent later. Interrupt error codes are therefore
+excluded from the abort in the same way as -EAGAIN.
+
+Fixes: b341ca51d267 ("tls: Fix tls_sw_sendmsg error handling")
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Link: https://patch.msgid.link/20260805063109.1772314-1-maxbr@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index ba95f9d927a35..a8c3adc0fad0a 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -458,7 +458,7 @@ int tls_tx_records(struct sock *sk, int flags)
+       }
+ tx_err:
+-      if (rc < 0 && rc != -EAGAIN)
++      if (rc < 0 && rc != -EAGAIN && rc != -EINTR && rc != -ERESTARTSYS)
+               tls_err_abort(sk, rc);
+       return rc;
+-- 
+2.53.0
+
diff --git a/queue-7.1/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch b/queue-7.1/udp-fix-potential-use-after-free-in-tunnel-segmentat.patch
new file mode 100644 (file)
index 0000000..dbab0c3
--- /dev/null
@@ -0,0 +1,53 @@
+From 4d887cfb549136a384554092992fa1717cca2bca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 17:35:54 +0800
+Subject: udp: fix potential use-after-free in tunnel segmentation
+
+From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+
+[ Upstream commit d0f86fb36eb260abd10007b62c9dcc1028e03e61 ]
+
+__skb_udp_tunnel_segment() gets the UDP header before ensuring the
+tunnel header is in the skb head. If the pull reallocates skb->head,
+the saved UDP header pointer is no longer valid.
+
+Get the UDP header after the pull to avoid a potential use-after-free.
+
+Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
+Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp_offload.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 29651b1a0bc70..abcd3cc2d9a38 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -178,17 +178,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+       int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+       bool remcsum, need_csum, offload_csum, gso_partial;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+-      struct udphdr *uh = udp_hdr(skb);
+       u16 mac_offset = skb->mac_header;
+       __be16 protocol = skb->protocol;
+       u16 mac_len = skb->mac_len;
+       int udp_offset, outer_hlen;
++      struct udphdr *uh;
+       __wsum partial;
+       bool need_ipsec;
+       if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+               goto out;
++      uh = udp_hdr(skb);
++
+       /* Adjust partial header checksum to negate old length.
+        * We cannot rely on the value contained in uh->len as it is
+        * possible that the actual value exceeds the boundaries of the
+-- 
+2.53.0
+
diff --git a/queue-7.1/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch b/queue-7.1/vdpa-mlx5-fix-buffer-length-in-create_direct_keys.patch
new file mode 100644 (file)
index 0000000..b7d8707
--- /dev/null
@@ -0,0 +1,61 @@
+From 50bf7bb5aae5e875c8024d78aa49378684d33244 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jul 2026 16:15:37 +0200
+Subject: vdpa/mlx5: Fix buffer length in create_direct_keys()
+
+From: Christian Borntraeger <borntraeger@linux.ibm.com>
+
+[ Upstream commit 727e1f569855df83579edbd73dcb4a0723543a12 ]
+
+We have seen in our CI the following KASAN message:
+BUG: KASAN: slab-out-of-bounds in cmd_exec+0x550/0xca0 [mlx5_core]
+Read of size 272 at addr 0000000176795020 by task qemu-system-s39/82764
+[...]
+[<000011388ab3a7a0>] cmd_exec+0x550/0xca0 [mlx5_core]
+[<000011388ab3b61c>] mlx5_cmd_exec_cb+0x25c/0x4f0 [mlx5_core]
+[<000011388b21e82e>] mlx5_vdpa_exec_async_cmds+0x22e/0x5e0 [mlx5_vdpa]
+[<000011388b21fd44>] create_direct_keys+0x954/0xef0 [mlx5_vdpa]
+[...]
+The buggy address is located 4128 bytes inside of
+allocated 4384-byte region [0000000176794000, 0000000176795120)
+
+So in essence we read 16 bytes beyond 4384-byte allocation.
+create_direct_keys calculates the pointer and length for in and out
+buffers.
+The size calculation for in includes the entire structure
+size (out + in + mtt[]) but the pointer passed to cmd_exec points only
+to the 'in' field, skipping the 'out' field.
+
+This causes mlx5_copy_to_msg() to read beyond the allocated buffer
+by sizeof(out) bytes when copying command data.
+
+Properly calculate the input size to match the pointer and allocation size.
+
+Fixes: 0071b138d44a ("vdpa/mlx5: Create direct MKEYs in parallel")
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Tested-by: Dragos Tatulea <dtatulea@nvidia.com>
+Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <20260706141537.3510294-1-borntraeger@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/core/mr.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
+index deb56e948f785..ce204ae3dfda3 100644
+--- a/drivers/vdpa/mlx5/core/mr.c
++++ b/drivers/vdpa/mlx5/core/mr.c
+@@ -234,7 +234,8 @@ static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *
+               cmds[i].out = cmd_mem->out;
+               cmds[i].outlen = sizeof(cmd_mem->out);
+               cmds[i].in = cmd_mem->in;
+-              cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount);
++              cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount) -
++                              offsetof(struct mlx5_create_mkey_mem, in);
+               fill_create_direct_mr(mvdev, dmr, cmd_mem);
+-- 
+2.53.0
+
diff --git a/queue-7.1/vhost-scsi-reject-feature-changes-after-endpoint.patch b/queue-7.1/vhost-scsi-reject-feature-changes-after-endpoint.patch
new file mode 100644 (file)
index 0000000..c73469b
--- /dev/null
@@ -0,0 +1,102 @@
+From 41015a3d10237e553b63a38eb14decb24534cf9b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Jul 2026 22:43:14 +0800
+Subject: vhost-scsi: reject feature changes after endpoint
+
+From: Jia Jia <physicalmtea@gmail.com>
+
+[ Upstream commit 42bc45df5905e2b7dccb72adaf7730f66cfbe03f ]
+
+vhost_scsi_setup_vq_cmds() runs from VHOST_SCSI_SET_ENDPOINT and allocates
+each command's protection scatterlist array (prot_sgl) according to the
+acknowledged VIRTIO_SCSI_F_T10_PI bit.  The command pools are not rebuilt
+when VHOST_SET_FEATURES changes that bit later.
+
+Although virtio feature bits must not change after feature negotiation,
+vhost_scsi_set_features() currently accepts such a request after the
+endpoint is active and updates acked_features.  Enabling T10-PI after
+endpoint setup therefore leaves prot_sgl NULL while the I/O path follows
+the new feature bit.
+
+For a 129-page protection payload, vhost_scsi_mapal() passes the missing
+first chunk to sg_alloc_table_chained():
+
+  sg_alloc_table_chained(table, 129, first_chunk=NULL,
+                         nents_first_chunk=inline_sg_cnt)
+
+sg_pool_index() then hits:
+
+  BUG_ON(nents > SG_CHUNK_SIZE);   /* 129 > 128 */
+
+The kernel reported the following call trace and register state:
+
+  Call Trace:
+   <TASK>
+   ? __sg_alloc_table+0x1d8/0x250
+   ? __pfx_vhost_run_work_list+0x10/0x10 [vhost]
+   sg_alloc_table_chained+0x59/0xf0
+   ? __pfx_sg_pool_alloc+0x10/0x10
+   ? vhost_scsi_calc_sgls.constprop.0+0x43/0x60 [vhost_scsi]
+   vhost_scsi_handle_vq+0xf02/0x1700 [vhost_scsi]
+   ? __pfx_vhost_scsi_handle_vq+0x10/0x10 [vhost_scsi]
+   vhost_scsi_handle_kick+0x37/0x50 [vhost_scsi]
+   vhost_run_work_list+0x8e/0xd0 [vhost]
+   vhost_task_fn+0xe1/0x210
+   ret_from_fork+0x348/0x540
+   </TASK>
+
+  RIP: 0010:0x4
+  CR2 = 0x4
+  RSP: 0018:ffffc90000dbf940 EFLAGS: 00010202
+  RAX: ffffffff82396810 RBX: ffff88811dc28b80 RCX: 0000000000000000
+  RDX: 0000000000000000 RSI: 0000000000000820 RDI: 0000000000000081
+
+VHOST_F_LOG_ALL is a vhost-specific runtime feature and remains the only
+exception.
+
+Reject changes to any feature other than VHOST_F_LOG_ALL while the
+endpoint is active.  This preserves the existing runtime log toggle while
+preventing feature-dependent command resources and data-path state from
+becoming inconsistent.  Userspace must clear the endpoint before changing
+any other negotiated feature and set the endpoint up again afterward.
+
+Fixes: bf2d650391be ("vhost-scsi: Allocate T10 PI structs only when enabled")
+Signed-off-by: Jia Jia <physicalmtea@gmail.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <20260726144314.1652934-1-physicalmtea@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/scsi.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index c79197edb1637..904bd842cdd84 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -2227,6 +2227,7 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
+ {
+       struct vhost_virtqueue *vq;
+       bool is_log, was_log;
++      u64 old_features;
+       int i;
+       if (features & ~VHOST_SCSI_FEATURES)
+@@ -2242,6 +2243,14 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
+       if (!vs->dev.nvqs)
+               goto out;
++      old_features = vs->vqs[0].vq.acked_features;
++      if (vs->vs_tpg &&
++          ((features ^ old_features) &
++           ~(1ULL << VHOST_F_LOG_ALL))) {
++              mutex_unlock(&vs->dev.mutex);
++              return -EBUSY;
++      }
++
+       is_log = features & (1 << VHOST_F_LOG_ALL);
+       /*
+        * All VQs should have same feature.
+-- 
+2.53.0
+
diff --git a/queue-7.1/vhost-scsi-validate-t10-pi-scatterlist-counts.patch b/queue-7.1/vhost-scsi-validate-t10-pi-scatterlist-counts.patch
new file mode 100644 (file)
index 0000000..09116f4
--- /dev/null
@@ -0,0 +1,63 @@
+From cbac41a9e7cc85a5510128b6215d867dbe6460b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 16:18:41 +0800
+Subject: vhost-scsi: Validate T10 PI scatterlist counts
+
+From: Linfeng Sun <slf@hdu.edu.cn>
+
+[ Upstream commit d876c493fc4b811941bfeb4c80beb2dfc4bf025e ]
+
+When T10 PI is negotiated, vhost-scsi splits protection bytes from
+the data iterator before mapping the request scatterlists. A malformed
+request can claim protection bytes that cover or exceed the full payload
+length. The former leaves no data bytes to map, while the latter
+underflows exp_data_len before advancing the iterator. Both cases can let
+a zero data SGL count reach sg_alloc_table_chained(), which triggers
+BUG_ON(!nents).
+
+Reject protection lengths that cover or exceed the payload before
+subtracting prot_bytes and advancing the iterator. Also propagate
+negative errors from the protection SGL calculation before calling the
+allocator, matching the data SGL path.
+
+Fixes: bca939d5bcd0 ("vhost-scsi: Dynamically allocate scatterlists")
+Suggested-by: Jia Jia <physicalmtea@gmail.com>
+Signed-off-by: Jia Jia <physicalmtea@gmail.com>
+Assisted-by: OpenAI-Codex:GPT-5
+Signed-off-by: Linfeng Sun <linfeng.sun.dev@gmail.com>
+Message-ID: <20260727081841.923151-1-slf@hdu.edu.cn>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/scsi.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index 9a1253b9d8c50..c79197edb1637 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -972,6 +972,9 @@ vhost_scsi_mapal(struct vhost_scsi *vs, struct vhost_scsi_cmd *cmd,
+       if (prot_bytes) {
+               sgl_count = vhost_scsi_calc_sgls(prot_iter, prot_bytes,
+                                                VHOST_SCSI_PREALLOC_PROT_SGLS);
++              if (sgl_count < 0)
++                      return sgl_count;
++
+               cmd->prot_table.sgl = cmd->prot_sgl;
+               ret = sg_alloc_table_chained(&cmd->prot_table, sgl_count,
+                                            cmd->prot_table.sgl,
+@@ -1416,6 +1419,11 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
+                        * actual data payload length.
+                        */
+                       if (prot_bytes) {
++                              if (prot_bytes >= exp_data_len) {
++                                      vq_err(vq, "Protection data exceeds payload length\n");
++                                      goto err;
++                              }
++
+                               exp_data_len -= prot_bytes;
+                               prot_iter = data_iter;
+                               iov_iter_truncate(&prot_iter, prot_bytes);
+-- 
+2.53.0
+
diff --git a/queue-7.1/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch b/queue-7.1/vhost-vdpa-reject-overflowing-pa-map-page-counts-on-.patch
new file mode 100644 (file)
index 0000000..246b92c
--- /dev/null
@@ -0,0 +1,56 @@
+From e7db3f64447716fe57d50db75a68cca25e533410 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2026 15:02:02 -0700
+Subject: vhost/vdpa: reject overflowing PA map page counts on 32-bit
+
+From: Yousef Alhouseen <alhouseenyousef@gmail.com>
+
+[ Upstream commit 0619aaa34c0c2a2dcb07f0e9c8a34e7efb8c4cdf ]
+
+vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map
+size before computing the number of pages to pin. On 32-bit systems,
+where unsigned long is narrower than u64, that addition can overflow and
+the code can pin and map fewer pages than the requested IOTLB range.
+
+Reject sizes that overflow the unsigned long page-count calculation.
+
+Fixes: 22af48cf91aa ("vdpa: factor out vhost_vdpa_pa_map() and vhost_vdpa_pa_unmap()")
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <CAMuQ4bX-iDvcUOPPY+NLz95tkRJYwWqvzAr=U48uNaub_HZLGw@mail.gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index ef642bc9f97e1..c3d913bd7cac7 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -1109,6 +1109,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       unsigned int gup_flags = FOLL_LONGTERM;
+       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+       unsigned long lock_limit, sz2pin, nchunks, i;
++      unsigned long page_offset;
+       u64 start = iova;
+       long pinned;
+       int ret = 0;
+@@ -1121,7 +1122,13 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
+       if (perm & VHOST_ACCESS_WO)
+               gup_flags |= FOLL_WRITE;
+-      npages = PFN_UP(size + (iova & ~PAGE_MASK));
++      page_offset = iova & ~PAGE_MASK;
++      if (size > ULONG_MAX - page_offset) {
++              ret = -EINVAL;
++              goto free;
++      }
++
++      npages = PFN_UP(size + page_offset);
+       if (!npages) {
+               ret = -EINVAL;
+               goto free;
+-- 
+2.53.0
+
diff --git a/queue-7.1/vhost_iotlb-bound-map-allocation-in-add_range.patch b/queue-7.1/vhost_iotlb-bound-map-allocation-in-add_range.patch
new file mode 100644 (file)
index 0000000..9ec0ae5
--- /dev/null
@@ -0,0 +1,357 @@
+From 9cf7692bd15012285dfa28e3de0a11cb858a16b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Jun 2026 21:00:05 +0800
+Subject: vhost_iotlb: bound map allocation in add_range
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Linfeng Sun  <linfeng.sun.dev@gamil.com>
+
+[ Upstream commit 1ed35ac7f3fe2b4396bdd29ac3a7f0ebc0829e94 ]
+
+vhost_iotlb_add_range_ctx() only retires an old entry when the table
+has a non-zero limit, has exactly reached that limit and has
+VHOST_IOTLB_FLAG_RETIRE set. Non-retiring tables can keep allocating
+entries after reaching their configured limit.
+
+Existing vhost devices allocate their IOTLB with max_iotlb_entries from
+vhost.c, which defaults to 2048 and is tunable by module parameter. Use
+the caller-provided limit at the allocation point instead of adding a
+separate default in the common IOTLB helper, and reject non-positive
+values in vhost paths that can report an error.
+
+Other vhost IOTLB users should not create zero-limit tables when entries
+can be populated from userspace or guest-controlled requests. Add
+caller-side max_iotlb_entries parameters for mlx5 vDPA, VDUSE and
+vhost-vDPA. Reject non-positive VDUSE and vhost-vDPA values, and require
+at least two entries for vdpa_sim and mlx5 vDPA paths that install
+full-range mappings, since those mappings are split into two IOTLB
+entries.
+
+Handle full-range mappings in the common helper by checking that the
+IOTLB can hold both split entries before inserting the first half. This
+avoids returning an error after leaving a half mapping behind.
+
+When the table is full, keep the existing retire behavior for retiring
+tables and return -ENOSPC for non-retiring tables. Reuse the retired map
+node instead of freeing it and allocating a replacement, so a stream of
+IOTLB updates cannot keep forcing GFP_ATOMIC allocations after the table
+has reached its limit. If a zero-limit IOTLB still reaches the common
+helper, treat it as a configuration error and return -EINVAL.
+
+I found this bug myself, though the patch was written with AI assistance.
+
+Fixes: 0bbe30668d89 ("vhost: factor out IOTLB")
+Assisted-by: OpenAI-Codex:GPT-5
+Signed-off-by: Linfeng Sun <linfeng.sun.dev@gamil.com>
+Message-ID: <AMYAtgAiKmgYcSQT5ukl-4qq.3.1781960405943.Hmail.241270009@hdu.edu.cn>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/core/mlx5_vdpa.h   |  2 ++
+ drivers/vdpa/mlx5/core/mr.c          |  5 ++-
+ drivers/vdpa/mlx5/core/resources.c   | 11 ++++++-
+ drivers/vdpa/vdpa_sim/vdpa_sim.c     | 10 ++++--
+ drivers/vdpa/vdpa_user/iova_domain.c | 11 ++++++-
+ drivers/vhost/iotlb.c                | 47 +++++++++++++++++++---------
+ drivers/vhost/vdpa.c                 |  9 +++++-
+ drivers/vhost/vhost.c                |  8 +++++
+ 8 files changed, 82 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h
+index 2cedf7e2dbc49..42f2f44b383c7 100644
+--- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h
++++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h
+@@ -11,6 +11,8 @@
+ #define MLX5V_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
++extern int mlx5_vdpa_max_iotlb_entries;
++
+ struct mlx5_vdpa_direct_mr {
+       u64 start;
+       u64 end;
+diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
+index 42c2705077a6d..deb56e948f785 100644
+--- a/drivers/vdpa/mlx5/core/mr.c
++++ b/drivers/vdpa/mlx5/core/mr.c
+@@ -777,6 +777,9 @@ static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
+ {
+       int err;
++      if (mlx5_vdpa_max_iotlb_entries < 2)
++              return -EINVAL;
++
+       if (iotlb)
+               err = create_user_mr(mvdev, mr, iotlb);
+       else
+@@ -785,7 +788,7 @@ static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
+       if (err)
+               return err;
+-      mr->iotlb = vhost_iotlb_alloc(0, 0);
++      mr->iotlb = vhost_iotlb_alloc(mlx5_vdpa_max_iotlb_entries, 0);
+       if (!mr->iotlb) {
+               err = -ENOMEM;
+               goto err_mr;
+diff --git a/drivers/vdpa/mlx5/core/resources.c b/drivers/vdpa/mlx5/core/resources.c
+index aeae31d0cefae..28a4d7a35bf4e 100644
+--- a/drivers/vdpa/mlx5/core/resources.c
++++ b/drivers/vdpa/mlx5/core/resources.c
+@@ -3,8 +3,14 @@
+ #include <linux/iova.h>
+ #include <linux/mlx5/driver.h>
++#include <linux/moduleparam.h>
+ #include "mlx5_vdpa.h"
++int mlx5_vdpa_max_iotlb_entries = 2048;
++module_param_named(max_iotlb_entries, mlx5_vdpa_max_iotlb_entries, int, 0444);
++MODULE_PARM_DESC(max_iotlb_entries,
++               "Maximum number of iotlb entries. (default: 2048)");
++
+ static int alloc_pd(struct mlx5_vdpa_dev *dev, u32 *pdn, u16 uid)
+ {
+       struct mlx5_core_dev *mdev = dev->mdev;
+@@ -229,7 +235,10 @@ int mlx5_vdpa_destroy_mkey(struct mlx5_vdpa_dev *mvdev, u32 mkey)
+ static int init_ctrl_vq(struct mlx5_vdpa_dev *mvdev)
+ {
+-      mvdev->cvq.iotlb = vhost_iotlb_alloc(0, 0);
++      if (mlx5_vdpa_max_iotlb_entries < 2)
++              return -EINVAL;
++
++      mvdev->cvq.iotlb = vhost_iotlb_alloc(mlx5_vdpa_max_iotlb_entries, 0);
+       if (!mvdev->cvq.iotlb)
+               return -ENOMEM;
+diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
+index 8cb1cc2ea1391..4d116644851d9 100644
+--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
++++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
+@@ -34,7 +34,7 @@ MODULE_PARM_DESC(batch_mapping, "Batched mapping 1 -Enable; 0 - Disable");
+ static int max_iotlb_entries = 2048;
+ module_param(max_iotlb_entries, int, 0444);
+ MODULE_PARM_DESC(max_iotlb_entries,
+-               "Maximum number of iotlb entries for each address space. 0 means unlimited. (default: 2048)");
++               "Maximum number of iotlb entries for each address space. (default: 2048)");
+ static bool use_va = true;
+ module_param(use_va, bool, 0444);
+@@ -201,6 +201,8 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
+       if (!dev_attr->alloc_size)
+               return ERR_PTR(-EINVAL);
++      if (max_iotlb_entries < 2)
++              return ERR_PTR(-EINVAL);
+       if (config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) {
+               if (config->device_features &
+@@ -261,8 +263,10 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
+       for (i = 0; i < vdpasim->dev_attr.nas; i++) {
+               vhost_iotlb_init(&vdpasim->iommu[i], max_iotlb_entries, 0);
+-              vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, 0,
+-                                    VHOST_MAP_RW);
++              ret = vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX,
++                                          0, VHOST_MAP_RW);
++              if (ret)
++                      goto err_iommu;
+               vdpasim->iommu_pt[i] = true;
+       }
+diff --git a/drivers/vdpa/vdpa_user/iova_domain.c b/drivers/vdpa/vdpa_user/iova_domain.c
+index 4dc76c0d0d13d..b6c958224b7ce 100644
+--- a/drivers/vdpa/vdpa_user/iova_domain.c
++++ b/drivers/vdpa/vdpa_user/iova_domain.c
+@@ -12,11 +12,17 @@
+ #include <linux/file.h>
+ #include <linux/anon_inodes.h>
+ #include <linux/highmem.h>
++#include <linux/moduleparam.h>
+ #include <linux/vmalloc.h>
+ #include <linux/vdpa.h>
+ #include "iova_domain.h"
++static int max_iotlb_entries = 2048;
++module_param(max_iotlb_entries, int, 0444);
++MODULE_PARM_DESC(max_iotlb_entries,
++               "Maximum number of iotlb entries. (default: 2048)");
++
+ static int vduse_iotlb_add_range(struct vduse_iova_domain *domain,
+                                u64 start, u64 last,
+                                u64 addr, unsigned int perm,
+@@ -622,11 +628,14 @@ vduse_domain_create(unsigned long iova_limit, size_t bounce_size)
+       if (iova_limit <= bounce_size)
+               return NULL;
++      if (max_iotlb_entries <= 0)
++              return NULL;
++
+       domain = kzalloc_obj(*domain);
+       if (!domain)
+               return NULL;
+-      domain->iotlb = vhost_iotlb_alloc(0, 0);
++      domain->iotlb = vhost_iotlb_alloc(max_iotlb_entries, 0);
+       if (!domain->iotlb)
+               goto err_iotlb;
+diff --git a/drivers/vhost/iotlb.c b/drivers/vhost/iotlb.c
+index e1414c774c344..a1d4376a5b872 100644
+--- a/drivers/vhost/iotlb.c
++++ b/drivers/vhost/iotlb.c
+@@ -20,6 +20,14 @@ INTERVAL_TREE_DEFINE(struct vhost_iotlb_map,
+                    rb, __u64, __subtree_last,
+                    START, LAST, static inline, vhost_iotlb_itree);
++static void vhost_iotlb_map_unlink(struct vhost_iotlb *iotlb,
++                                 struct vhost_iotlb_map *map)
++{
++      vhost_iotlb_itree_remove(map, &iotlb->root);
++      list_del(&map->link);
++      iotlb->nmaps--;
++}
++
+ /**
+  * vhost_iotlb_map_free - remove a map node and free it
+  * @iotlb: the IOTLB
+@@ -28,10 +36,8 @@ INTERVAL_TREE_DEFINE(struct vhost_iotlb_map,
+ void vhost_iotlb_map_free(struct vhost_iotlb *iotlb,
+                         struct vhost_iotlb_map *map)
+ {
+-      vhost_iotlb_itree_remove(map, &iotlb->root);
+-      list_del(&map->link);
++      vhost_iotlb_map_unlink(iotlb, map);
+       kfree(map);
+-      iotlb->nmaps--;
+ }
+ EXPORT_SYMBOL_GPL(vhost_iotlb_map_free);
+@@ -57,14 +63,25 @@ int vhost_iotlb_add_range_ctx(struct vhost_iotlb *iotlb,
+       if (last < start)
+               return -EFAULT;
++      if (!iotlb->limit)
++              return -EINVAL;
++
+       /* If the range being mapped is [0, ULONG_MAX], split it into two entries
+        * otherwise its size would overflow u64.
+        */
+       if (start == 0 && last == ULONG_MAX) {
+               u64 mid = last / 2;
+-              int err = vhost_iotlb_add_range_ctx(iotlb, start, mid, addr,
+-                              perm, opaque);
++              int err;
++
++              if (iotlb->limit < 2)
++                      return -ENOSPC;
++              if (!(iotlb->flags & VHOST_IOTLB_FLAG_RETIRE) &&
++                  iotlb->nmaps > iotlb->limit - 2)
++                      return -ENOSPC;
++
++              err = vhost_iotlb_add_range_ctx(iotlb, start, mid, addr,
++                                              perm, opaque);
+               if (err)
+                       return err;
+@@ -72,17 +89,19 @@ int vhost_iotlb_add_range_ctx(struct vhost_iotlb *iotlb,
+               start = mid + 1;
+       }
+-      if (iotlb->limit &&
+-          iotlb->nmaps == iotlb->limit &&
+-          iotlb->flags & VHOST_IOTLB_FLAG_RETIRE) {
+-              map = list_first_entry(&iotlb->list, typeof(*map), link);
+-              vhost_iotlb_map_free(iotlb, map);
++      if (iotlb->nmaps >= iotlb->limit) {
++              if (iotlb->flags & VHOST_IOTLB_FLAG_RETIRE) {
++                      map = list_first_entry(&iotlb->list, typeof(*map), link);
++                      vhost_iotlb_map_unlink(iotlb, map);
++              } else {
++                      return -ENOSPC;
++              }
++      } else {
++              map = kmalloc_obj(*map, GFP_ATOMIC);
++              if (!map)
++                      return -ENOMEM;
+       }
+-      map = kmalloc_obj(*map, GFP_ATOMIC);
+-      if (!map)
+-              return -ENOMEM;
+-
+       map->start = start;
+       map->size = last - start + 1;
+       map->last = last;
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index ac55275fa0d0a..ef642bc9f97e1 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -34,6 +34,11 @@ enum {
+ #define VHOST_VDPA_DEV_MAX (1U << MINORBITS)
++static int max_iotlb_entries = 2048;
++module_param(max_iotlb_entries, int, 0444);
++MODULE_PARM_DESC(max_iotlb_entries,
++               "Maximum number of iotlb entries. (default: 2048)");
++
+ #define VHOST_VDPA_IOTLB_BUCKETS 16
+ struct vhost_vdpa_as {
+@@ -109,12 +114,14 @@ static struct vhost_vdpa_as *vhost_vdpa_alloc_as(struct vhost_vdpa *v, u32 asid)
+       if (asid >= v->vdpa->nas)
+               return NULL;
++      if (max_iotlb_entries <= 0)
++              return NULL;
+       as = kmalloc_obj(*as);
+       if (!as)
+               return NULL;
+-      vhost_iotlb_init(&as->iotlb, 0, 0);
++      vhost_iotlb_init(&as->iotlb, max_iotlb_entries, 0);
+       as->id = asid;
+       hlist_add_head(&as->hash_link, head);
+diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
+index db329a6f61458..6ec0616932382 100644
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -1137,6 +1137,9 @@ EXPORT_SYMBOL_GPL(vhost_dev_set_owner);
+ static struct vhost_iotlb *iotlb_alloc(void)
+ {
++      if (max_iotlb_entries <= 0)
++              return NULL;
++
+       return vhost_iotlb_alloc(max_iotlb_entries,
+                                VHOST_IOTLB_FLAG_RETIRE);
+ }
+@@ -1981,6 +1984,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
+               return -EOPNOTSUPP;
+       if (mem.nregions > max_mem_regions)
+               return -E2BIG;
++      if (max_iotlb_entries <= 0)
++              return -EINVAL;
+       newmem = kvzalloc_flex(*newmem, regions, mem.nregions);
+       if (!newmem)
+               return -ENOMEM;
+@@ -2275,6 +2280,9 @@ int vhost_init_device_iotlb(struct vhost_dev *d)
+       struct vhost_iotlb *niotlb, *oiotlb;
+       int i;
++      if (max_iotlb_entries <= 0)
++              return -EINVAL;
++
+       niotlb = iotlb_alloc();
+       if (!niotlb)
+               return -ENOMEM;
+-- 
+2.53.0
+
diff --git a/queue-7.1/watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch b/queue-7.1/watchdog-at91sam9_wdt-prevent-timer-rearm-during-tea.patch
new file mode 100644 (file)
index 0000000..bf652c8
--- /dev/null
@@ -0,0 +1,51 @@
+From 24a2cf6f22ea340bd70f5c98847b2c8070fe8cce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2026 14:06:13 +0800
+Subject: watchdog: at91sam9_wdt: prevent timer rearm during teardown
+
+From: Hongyan Xu <getshell@seu.edu.cn>
+
+[ Upstream commit 8444d66aa6b6e7fe0a26fa1a00a11cb4d0523783 ]
+
+at91_ping() rearms the watchdog timer from its callback. timer_delete()
+neither waits for a running callback nor prevents it from rearming the
+timer, so probe failure or driver removal can leave the timer accessing the
+devm-allocated at91wdt after it has been freed.
+
+Use timer_shutdown_sync() on both teardown paths. It waits for a running
+callback and rejects any attempt by the callback to rearm the timer.
+
+Fixes: 5161b31dc39a ("watchdog: at91sam9_wdt: better watchdog support")
+Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
+Link: https://lore.kernel.org/r/20260806060613.1830-1-getshell@seu.edu.cn
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/at91sam9_wdt.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
+index aba66b8e9d033..80ba04df54adf 100644
+--- a/drivers/watchdog/at91sam9_wdt.c
++++ b/drivers/watchdog/at91sam9_wdt.c
+@@ -242,7 +242,7 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
+       return 0;
+ out_stop_timer:
+-      timer_delete(&wdt->timer);
++      timer_shutdown_sync(&wdt->timer);
+       return err;
+ }
+@@ -378,7 +378,7 @@ static void at91wdt_remove(struct platform_device *pdev)
+       watchdog_unregister_device(&wdt->wdd);
+       pr_warn("I quit now, hardware will probably reboot!\n");
+-      timer_delete(&wdt->timer);
++      timer_shutdown_sync(&wdt->timer);
+ }
+ #if defined(CONFIG_OF)
+-- 
+2.53.0
+
diff --git a/queue-7.1/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch b/queue-7.1/watchdog-bd96801_wdt-fix-timeout-for-enabled-wdg.patch
new file mode 100644 (file)
index 0000000..3285696
--- /dev/null
@@ -0,0 +1,68 @@
+From ab60f9ce8de021d0765590fb5369b71434ee7249 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:36:28 +0300
+Subject: watchdog: bd96801_wdt: Fix timeout for enabled WDG
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit 1246aa2b6ccc8944676bd24ff3e37cc56b93b51b ]
+
+When watchdog is enabled at the probe time, the bd96801 driver retrieves
+the timeout configuration from the registers to set-up the heart-beat
+values.
+
+As Sashiko pointed out at
+https://lore.kernel.org/all/20260722085819.495211F000E9@smtp.kernel.org/
+the timeout values are incorrectly computed in driver, resulting wrong
+heartbeat. This leads to devere problems if watchdog was enabled at probe
+time.
+
+According to the data-sheet, the "too fast" ping limit is configured as
+multiple of FASTNG_MIN. Furthermore, the "too slow" ping limit is
+configured as multiples of "too fast" timeout. The FASTNG_MIN is set to
+11, meaning 1.1 mS and "too fast" and "too slow" limits are computed from
+this. Hence, converting the limits to mS should be done by dividing by 10,
+not by dividing by USEC_PER_MSEC.
+
+Fix this by dividing the timeout values with correct scaling factor.
+
+While at it, fix whitespace problem (double empty line).
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Fixes: 09dad69757b6 ("watchdog: ROHM BD96801 PMIC WDG driver")
+Link: https://lore.kernel.org/r/amxskHmQbi9v-8_l@mva-rohm
+[groeck: Added reference to whitespace change to description]
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/bd96801_wdt.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/watchdog/bd96801_wdt.c b/drivers/watchdog/bd96801_wdt.c
+index 12b74fd2bc052..a25b7cf1488b2 100644
+--- a/drivers/watchdog/bd96801_wdt.c
++++ b/drivers/watchdog/bd96801_wdt.c
+@@ -169,7 +169,6 @@ static int bd96801_set_wdt_mode(struct wdtbd96801 *w, unsigned int hw_margin,
+       int fastng, slowng, type, ret, reg, mask;
+       struct device *dev = w->dev;
+-
+       if (hw_margin_min * 1000 > FASTNG_MAX_US) {
+               dev_err(dev, "Unsupported fast timeout %u uS [max %u]\n",
+                       hw_margin_min * 1000, FASTNG_MAX_US);
+@@ -258,10 +257,10 @@ static int bd96801_set_heartbeat_from_hw(struct wdtbd96801 *w,
+       fast = FASTNG_MIN << sel;
+       sel = (val & BD96801_WD_RATIO_MASK) + 1;
+-      w->wdt.max_hw_heartbeat_ms = (fast << sel) / USEC_PER_MSEC;
++      w->wdt.max_hw_heartbeat_ms = (fast << sel) / 10;
+       if ((conf_reg & BD96801_WD_TYPE_MASK) == BD96801_WD_TYPE_WIN)
+-              w->wdt.min_hw_heartbeat_ms = fast / USEC_PER_MSEC;
++              w->wdt.min_hw_heartbeat_ms = fast / 10;
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.1/xfs-handle-null-b_addr-in-xfs_buf_free.patch b/queue-7.1/xfs-handle-null-b_addr-in-xfs_buf_free.patch
new file mode 100644 (file)
index 0000000..28e72d0
--- /dev/null
@@ -0,0 +1,53 @@
+From 16669aa609ee79d30b125ceda917bb883e1bc2b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jul 2026 23:11:24 +0800
+Subject: xfs: handle NULL b_addr in xfs_buf_free
+
+From: Yun Zhou <yun.zhou@windriver.com>
+
+[ Upstream commit d852729c5f4f830fbe7413df032e29459b3daf83 ]
+
+When xfs_buf_alloc_backing_mem() fails, xfs_buf_free() is called with
+bp->b_addr still NULL.  The code falls through to the folio_put path
+which calls virt_to_folio(NULL), dereferencing an invalid address and
+causing a kernel crash.
+
+ Call Trace:
+  xfs_buf_free+0x25f/0x510
+  xfs_buf_alloc+0xc98/0x19b0
+  xfs_buf_find_insert+0x55/0x14d0
+  xfs_buf_get_map+0x122b/0x17c0
+  xfbtree_init_leaf_block+0x11c/0x4a0
+  xfbtree_init+0x1bb/0x460
+  xrep_rmap_setup_scan+0x100/0x1f0
+  xrep_rmapbt+0x41/0xc0
+
+Fix this by skipping folio_put() when bp->b_addr is NULL.
+
+Fixes: 5076a6040ca1 ("xfs: support in-memory buffer cache targets")
+Reported-by: syzbot+94c22d92f72f5a235b7d@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=94c22d92f72f5a235b7d
+Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_buf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
+index 0cea458f13536..23bd81fbc2788 100644
+--- a/fs/xfs/xfs_buf.c
++++ b/fs/xfs/xfs_buf.c
+@@ -114,7 +114,7 @@ xfs_buf_free(
+               vfree(bp->b_addr);
+       else if (bp->b_flags & _XBF_KMEM)
+               kfree(bp->b_addr);
+-      else
++      else if (bp->b_addr)
+               folio_put(virt_to_folio(bp->b_addr));
+       call_rcu(&bp->b_rcu, xfs_buf_free_callback);
+-- 
+2.53.0
+
diff --git a/queue-7.1/xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch b/queue-7.1/xsk-clear-metadata-pointer-when-no-timestamp-is-requ.patch
new file mode 100644 (file)
index 0000000..92f1713
--- /dev/null
@@ -0,0 +1,88 @@
+From d010e5c4b93c31a79f22e863510710c97a6966b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:56 -0700
+Subject: xsk: clear metadata pointer when no timestamp is requested
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 9f60a67df8d3c862503bee62bada8e7089cba438 ]
+
+User space can change metadata flags after request processing. Rereading
+them during completion can therefore make the kernel write a timestamp
+that was not requested when the packet was submitted.
+
+Clear the metadata pointer during request processing unless timestamp
+completion is requested. Completion handling can then use the pointer
+itself instead of rereading the flags.
+
+On the mlx5 multi-packet WQE path metadata is evaluated per batch:
+xsk_tx_metadata_request() runs only for the descriptor that starts a
+session, just like the checksum offload that is applied once through the
+shared WQE. Only that descriptor's pointer is reset, so completion
+handling can record a timestamp for the other descriptors of the session
+regardless of their own XDP_TXMD_FLAGS_TIMESTAMP bit. The write stays
+inside the metadata area; the single-WQE, other zero-copy, and generic
+paths reset the pointer per descriptor and are unaffected.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-4-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xdp_sock.h | 14 ++++++++++----
+ net/xdp/xsk.c          |  2 ++
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index 06c081feff42d..2b2eb9b9d580e 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -141,13 +141,16 @@ INDIRECT_CALLABLE_DECLARE(void xsk_destruct_skb(struct sk_buff *));
+ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+                                           struct xsk_tx_metadata_compl *compl)
+ {
++      compl->tx_timestamp = NULL;
++
+       if (!meta)
+               return;
+-      if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
+-              compl->tx_timestamp = &meta->completion.tx_timestamp;
+-      else
+-              compl->tx_timestamp = NULL;
++      /* we can only arrive here if the completion timestamp has been
++       * requested via XDP_TXMD_FLAGS_TIMESTAMP, see xsk_tx_metadata_request
++       */
++
++      compl->tx_timestamp = &meta->completion.tx_timestamp;
+ }
+ /**
+@@ -182,6 +185,9 @@ static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+               if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
+                       ops->tmo_request_checksum(meta->request.csum_start,
+                                                 meta->request.csum_offset, priv);
++
++      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++              *pmeta = NULL;
+ }
+ /**
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 855fe92358bac..8d84afb3ad629 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -997,6 +997,8 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+       if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+               skb->skb_mstamp_ns = meta->request.launch_time;
++      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++              meta = NULL;
+       xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.1/xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch b/queue-7.1/xsk-move-xsk_tx_metadata_request-to-xdp_sock_drv.h.patch
new file mode 100644 (file)
index 0000000..02aed72
--- /dev/null
@@ -0,0 +1,150 @@
+From c480ba05c7db88a29cdad6d2dcbaadacdb4273aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:58 -0700
+Subject: xsk: move xsk_tx_metadata_request() to xdp_sock_drv.h
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit ddd0d6c5bfe2fef7c7cf31f62265f29b7b9eb9ef ]
+
+xsk_tx_metadata_request() must validate metadata with
+xsk_buff_valid_tx_metadata(), which is defined in xdp_sock_drv.h. Move the
+helper there before adding that dependency. All callers already include
+the destination header, so this has no functional effect.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-6-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xdp_sock.h     | 43 --------------------------------------
+ include/net/xdp_sock_drv.h | 43 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 43 insertions(+), 43 deletions(-)
+
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index 2b2eb9b9d580e..6e70b320b399f 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -153,43 +153,6 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+       compl->tx_timestamp = &meta->completion.tx_timestamp;
+ }
+-/**
+- *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
+- *  and call appropriate xsk_tx_metadata_ops operation.
+- *  @pmeta: pointer to pointer to AF_XDP metadata area
+- *  @ops: pointer to struct xsk_tx_metadata_ops
+- *  @priv: pointer to driver-private aread
+- *
+- *  This function should be called by the networking device when
+- *  it prepares AF_XDP egress packet.
+- */
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
+-{
+-      const struct xsk_tx_metadata *meta = *pmeta;
+-
+-      if (!meta)
+-              return;
+-
+-      if (ops->tmo_request_launch_time)
+-              if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+-                      ops->tmo_request_launch_time(meta->request.launch_time,
+-                                                   priv);
+-
+-      if (ops->tmo_request_timestamp)
+-              if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
+-                      ops->tmo_request_timestamp(priv);
+-
+-      if (ops->tmo_request_checksum)
+-              if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
+-                      ops->tmo_request_checksum(meta->request.csum_start,
+-                                                meta->request.csum_offset, priv);
+-
+-      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
+-              *pmeta = NULL;
+-}
+-
+ /**
+  *  xsk_tx_metadata_complete - Evaluate AF_XDP TX metadata at completion
+  *  and call appropriate xsk_tx_metadata_ops operation.
+@@ -239,12 +202,6 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+ {
+ }
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
+-{
+-}
+-
+ static inline void xsk_tx_metadata_complete(struct xsk_tx_metadata_compl *compl,
+                                           const struct xsk_tx_metadata_ops *ops,
+                                           void *priv)
+diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
+index 68a7876013572..f87c4215673ed 100644
+--- a/include/net/xdp_sock_drv.h
++++ b/include/net/xdp_sock_drv.h
+@@ -271,6 +271,43 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+       return !(*flags & ~XDP_TXMD_FLAGS_VALID);
+ }
++/**
++ *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
++ *  and call appropriate xsk_tx_metadata_ops operation.
++ *  @pmeta: pointer to pointer to AF_XDP metadata area
++ *  @ops: pointer to struct xsk_tx_metadata_ops
++ *  @priv: pointer to driver-private aread
++ *
++ *  This function should be called by the networking device when
++ *  it prepares AF_XDP egress packet.
++ */
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
++                                         const struct xsk_tx_metadata_ops *ops,
++                                         void *priv)
++{
++      const struct xsk_tx_metadata *meta = *pmeta;
++
++      if (!meta)
++              return;
++
++      if (ops->tmo_request_launch_time)
++              if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++                      ops->tmo_request_launch_time(meta->request.launch_time,
++                                                   priv);
++
++      if (ops->tmo_request_timestamp)
++              if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
++                      ops->tmo_request_timestamp(priv);
++
++      if (ops->tmo_request_checksum)
++              if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
++                      ops->tmo_request_checksum(meta->request.csum_start,
++                                                meta->request.csum_offset, priv);
++
++      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++              *pmeta = NULL;
++}
++
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+@@ -483,6 +520,12 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+       return false;
+ }
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
++                                         const struct xsk_tx_metadata_ops *ops,
++                                         void *priv)
++{
++}
++
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+-- 
+2.53.0
+
diff --git a/queue-7.1/xsk-pass-tx-metadata-pointer-by-reference.patch b/queue-7.1/xsk-pass-tx-metadata-pointer-by-reference.patch
new file mode 100644 (file)
index 0000000..7efb30e
--- /dev/null
@@ -0,0 +1,203 @@
+From 6ff3a7f0577e000c708ced304c826656f6d57191 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:55 -0700
+Subject: xsk: pass TX metadata pointer by reference
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 19366db6dfccac9b0867a151678cd7b89fb8fd99 ]
+
+Completion handling needs to know whether a timestamp was requested when
+the metadata was processed. Let xsk_tx_metadata_request() update the
+caller's metadata pointer so that decision can be carried forward without
+rereading user-controlled flags.
+
+This only changes the interface; behavior remains unchanged.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-3-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igc/igc_main.c          |  2 +-
+ drivers/net/ethernet/mellanox/mlx5/core/en.h       |  2 +-
+ drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c   | 14 +++++++++-----
+ drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h   |  4 ++--
+ .../net/ethernet/mellanox/mlx5/core/en/xsk/tx.c    |  2 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  2 +-
+ include/net/libeth/xsk.h                           |  2 +-
+ include/net/xdp_sock.h                             |  8 +++++---
+ 8 files changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index c0508d2615923..13ddf6cc52eea 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -3082,7 +3082,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
+               meta_req.tx_buffer = bi;
+               meta_req.meta = meta;
+               meta_req.used_desc = 0;
+-              xsk_tx_metadata_request(meta, &igc_xsk_tx_metadata_ops,
++              xsk_tx_metadata_request(&meta, &igc_xsk_tx_metadata_ops,
+                                       &meta_req);
+               /* xsk_tx_metadata_request() may have updated next_to_use */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+index 6867a5aed42c0..822859c360e75 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+@@ -483,7 +483,7 @@ typedef int (*mlx5e_fp_xmit_xdp_frame_check)(struct mlx5e_xdpsq *);
+ typedef bool (*mlx5e_fp_xmit_xdp_frame)(struct mlx5e_xdpsq *,
+                                       struct mlx5e_xmit_data *,
+                                       int,
+-                                      struct xsk_tx_metadata *);
++                                      struct xsk_tx_metadata **);
+ struct mlx5e_xdpsq {
+       /* data path */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+index d8c7cb8837d74..dac5e9d4c8bdb 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+@@ -452,11 +452,11 @@ INDIRECT_CALLABLE_SCOPE int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq
+ INDIRECT_CALLABLE_SCOPE bool
+ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+-                   int check_result, struct xsk_tx_metadata *meta);
++                   int check_result, struct xsk_tx_metadata **meta);
+ INDIRECT_CALLABLE_SCOPE bool
+ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+-                         int check_result, struct xsk_tx_metadata *meta)
++                         int check_result, struct xsk_tx_metadata **meta)
+ {
+       struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
+       struct mlx5e_xdpsq_stats *stats = sq->stats;
+@@ -504,7 +504,10 @@ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptx
+                * and it's safe to complete it at any time.
+                */
+               mlx5e_xdp_mpwqe_session_start(sq);
+-              xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, &session->wqe->eth);
++              if (meta)
++                      xsk_tx_metadata_request(meta,
++                                              &mlx5e_xsk_tx_metadata_ops,
++                                              &session->wqe->eth);
+       }
+       mlx5e_xdp_mpwqe_add_dseg(sq, p, stats);
+@@ -535,7 +538,7 @@ INDIRECT_CALLABLE_SCOPE int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq)
+ INDIRECT_CALLABLE_SCOPE bool
+ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+-                   int check_result, struct xsk_tx_metadata *meta)
++                   int check_result, struct xsk_tx_metadata **meta)
+ {
+       struct mlx5e_xmit_data_frags *xdptxdf =
+               container_of(xdptxd, struct mlx5e_xmit_data_frags, xd);
+@@ -649,7 +652,8 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+       sq->pc += num_wqebbs;
+-      xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
++      if (meta)
++              xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
+       sq->doorbell_cseg = cseg;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+index 3c54f8962664f..5b8f4094d5530 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+@@ -114,11 +114,11 @@ extern const struct xsk_tx_metadata_ops mlx5e_xsk_tx_metadata_ops;
+ INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq,
+                                                         struct mlx5e_xmit_data *xdptxd,
+                                                         int check_result,
+-                                                        struct xsk_tx_metadata *meta));
++                                                        struct xsk_tx_metadata **meta));
+ INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq,
+                                                   struct mlx5e_xmit_data *xdptxd,
+                                                   int check_result,
+-                                                  struct xsk_tx_metadata *meta));
++                                                  struct xsk_tx_metadata **meta));
+ INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq));
+ INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq));
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
+index 8aeab4b21035c..3d19dad8f8688 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
+@@ -105,7 +105,7 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget)
+               ret = INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe,
+                                     mlx5e_xmit_xdp_frame, sq, &xdptxd,
+-                                    check_result, meta);
++                                    check_result, &meta);
+               if (unlikely(!ret)) {
+                       if (sq->mpwqe.wqe)
+                               mlx5e_xdp_mpwqe_complete(sq);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index f28367fbcaf81..622f571b30350 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2748,7 +2748,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+               meta_req.set_ic = &set_ic;
+               meta_req.tbs = tx_q->tbs;
+               meta_req.edesc = &tx_q->dma_entx[entry];
+-              xsk_tx_metadata_request(meta, &stmmac_xsk_tx_metadata_ops,
++              xsk_tx_metadata_request(&meta, &stmmac_xsk_tx_metadata_ops,
+                                       &meta_req);
+               if (set_ic) {
+                       tx_q->tx_count_frames = 0;
+diff --git a/include/net/libeth/xsk.h b/include/net/libeth/xsk.h
+index 82b5d21aae878..e2fa6bf6b1b31 100644
+--- a/include/net/libeth/xsk.h
++++ b/include/net/libeth/xsk.h
+@@ -205,7 +205,7 @@ __libeth_xsk_xmit_fill_buf_md(const struct xdp_desc *xdesc,
+       BUILD_BUG_ON(!__builtin_constant_p(tmo == libeth_xsktmo));
+       tmo = tmo == libeth_xsktmo ? &__libeth_xsktmo : tmo;
+-      xsk_tx_metadata_request(ctx.meta, tmo, &desc);
++      xsk_tx_metadata_request(&ctx.meta, tmo, &desc);
+       return desc;
+ }
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index 8b51876efbed1..06c081feff42d 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -153,17 +153,19 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+ /**
+  *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
+  *  and call appropriate xsk_tx_metadata_ops operation.
+- *  @meta: pointer to AF_XDP metadata area
++ *  @pmeta: pointer to pointer to AF_XDP metadata area
+  *  @ops: pointer to struct xsk_tx_metadata_ops
+  *  @priv: pointer to driver-private aread
+  *
+  *  This function should be called by the networking device when
+  *  it prepares AF_XDP egress packet.
+  */
+-static inline void xsk_tx_metadata_request(const struct xsk_tx_metadata *meta,
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+                                          const struct xsk_tx_metadata_ops *ops,
+                                          void *priv)
+ {
++      const struct xsk_tx_metadata *meta = *pmeta;
++
+       if (!meta)
+               return;
+@@ -231,7 +233,7 @@ static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta,
+ {
+ }
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata *meta,
++static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+                                          const struct xsk_tx_metadata_ops *ops,
+                                          void *priv)
+ {
+-- 
+2.53.0
+
diff --git a/queue-7.1/xsk-require-at-least-16-bytes-of-tx-metadata.patch b/queue-7.1/xsk-require-at-least-16-bytes-of-tx-metadata.patch
new file mode 100644 (file)
index 0000000..24d5e08
--- /dev/null
@@ -0,0 +1,45 @@
+From 512627f160ca90829a046eda233e2d84d5294d77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:54 -0700
+Subject: xsk: require at least 16 bytes of TX metadata
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 1bb30b181d9f0484e141f8411e15ed906d5c6780 ]
+
+AF_XDP accepts a TX metadata length as small as eight bytes, but every
+supported request needs the flags plus at least one eight-byte request
+field. Such short metadata also lets the kernel read beyond the registered
+area.
+
+Require 16 bytes rather than sizeof(struct xsk_tx_metadata) to preserve
+compatibility with applications that do not use launch-time metadata.
+
+Fixes: 341ac980eab9 ("xsk: Support tx_metadata_len")
+Reported-by: AutonomousCodeSecurity@microsoft.com
+Reported-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Link: https://lore.kernel.org/netdev/20260720155210.34229-1-blbllhy@gmail.com/
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-2-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xdp_umem.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
+index 58da2f4f4397a..cd8643360eb3a 100644
+--- a/net/xdp/xdp_umem.c
++++ b/net/xdp/xdp_umem.c
+@@ -210,6 +210,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
+       if (mr->flags & XDP_UMEM_TX_METADATA_LEN) {
+               if (mr->tx_metadata_len >= 256 || mr->tx_metadata_len % 8)
+                       return -EINVAL;
++              if (mr->tx_metadata_len < 16)
++                      return -EINVAL;
+               umem->tx_metadata_len = mr->tx_metadata_len;
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.1/xsk-validate-launch-time-metadata-size.patch b/queue-7.1/xsk-validate-launch-time-metadata-size.patch
new file mode 100644 (file)
index 0000000..95f06da
--- /dev/null
@@ -0,0 +1,117 @@
+From 50d4fd2f97145ce38d0d8265e5a2759f070fa284 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:57 -0700
+Subject: xsk: validate launch-time metadata size
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 439ce2dddf3d22129b9113a7881637256a35e936 ]
+
+Launch-time metadata extends beyond the first 16 bytes of struct
+xsk_tx_metadata. Reject the request when the registered metadata area does
+not contain the complete field.
+
+Snapshot the validated flags for the generic transmit path and use that
+snapshot for request and completion processing, avoiding inconsistent
+decisions if user space changes the flags concurrently.
+
+Note that only xsk_skb_metadata is properly using the flags,
+__xsk_buff_get_metadata ignores them. Next commits address that.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-5-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xdp_sock_drv.h | 17 +++++++++++++----
+ net/xdp/xsk.c              | 11 ++++++-----
+ 2 files changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
+index 46797645a0c24..68a7876013572 100644
+--- a/include/net/xdp_sock_drv.h
++++ b/include/net/xdp_sock_drv.h
+@@ -260,21 +260,28 @@ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+       0)
+ static inline bool
+-xsk_buff_valid_tx_metadata(const struct xsk_tx_metadata *meta)
++xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
++                         const struct xsk_tx_metadata *meta, u64 *flags)
+ {
+-      return !(meta->flags & ~XDP_TXMD_FLAGS_VALID);
++      *flags = READ_ONCE(meta->flags);
++      if (*flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++              if (pool->tx_metadata_len <
++                  offsetofend(struct xsk_tx_metadata, request.launch_time))
++                      return false;
++      return !(*flags & ~XDP_TXMD_FLAGS_VALID);
+ }
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+       struct xsk_tx_metadata *meta;
++      u64 flags;
+       if (!pool->tx_metadata_len)
+               return NULL;
+       meta = data - pool->tx_metadata_len;
+-      if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
++      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
+               return NULL; /* no way to signal the error to the user */
+       return meta;
+@@ -469,7 +476,9 @@ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+       return (struct xdp_desc_ctx){ };
+ }
+-static inline bool xsk_buff_valid_tx_metadata(struct xsk_tx_metadata *meta)
++static inline bool
++xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
++                         const struct xsk_tx_metadata *meta, u64 *flags)
+ {
+       return false;
+ }
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 8d84afb3ad629..95a9ff3d0bdb4 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -966,15 +966,16 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+ {
+       struct xsk_tx_metadata *meta = NULL;
+       u16 csum_start, csum_offset;
++      u64 flags;
+       if (unlikely(pool->tx_metadata_len == 0))
+               return -EINVAL;
+       meta = buffer - pool->tx_metadata_len;
+-      if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
++      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
+               return -EINVAL;
+-      if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) {
++      if (flags & XDP_TXMD_FLAGS_CHECKSUM) {
+               csum_start = READ_ONCE(meta->request.csum_start);
+               csum_offset = READ_ONCE(meta->request.csum_offset);
+@@ -995,9 +996,9 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+               }
+       }
+-      if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+-              skb->skb_mstamp_ns = meta->request.launch_time;
+-      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++      if (flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++              skb->skb_mstamp_ns = READ_ONCE(meta->request.launch_time);
++      if (!(flags & XDP_TXMD_FLAGS_TIMESTAMP))
+               meta = NULL;
+       xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta);
+-- 
+2.53.0
+
diff --git a/queue-7.1/xsk-validate-metadata-when-processing-requests.patch b/queue-7.1/xsk-validate-metadata-when-processing-requests.patch
new file mode 100644 (file)
index 0000000..a971398
--- /dev/null
@@ -0,0 +1,224 @@
+From 82be16f022eddf0677e1e3d31ffe5d518f26145c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 09:19:59 -0700
+Subject: xsk: validate metadata when processing requests
+
+From: Stanislav Fomichev <sdf.kernel@gmail.com>
+
+[ Upstream commit 849b1664dbda1cf6c63e0fd4f9dec23782b8c851 ]
+
+The zero-copy path validates TX metadata while obtaining the descriptor
+context, then reads it again later when preparing the hardware request.
+User space can change the metadata between those operations and bypass the
+original validation.
+
+Validate the metadata in xsk_tx_metadata_request() and use the resulting
+flags snapshot for every feature check. Read request fields once so all
+zero-copy drivers process only values observed after successful
+validation.
+
+Fixes: ca4419f15abd ("xsk: Add launch time hardware offload support to XDP Tx metadata")
+Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Link: https://patch.msgid.link/20260727161959.885642-7-sdf@fomichev.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igc/igc_main.c     |  2 +-
+ .../net/ethernet/mellanox/mlx5/core/en/xdp.c  |  5 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 +-
+ include/net/libeth/xsk.h                      |  2 +-
+ include/net/xdp_sock_drv.h                    | 51 ++++++++++---------
+ net/xdp/xsk_buff_pool.c                       |  6 +--
+ 6 files changed, 37 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index 13ddf6cc52eea..6525ecb666e4c 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -3082,7 +3082,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
+               meta_req.tx_buffer = bi;
+               meta_req.meta = meta;
+               meta_req.used_desc = 0;
+-              xsk_tx_metadata_request(&meta, &igc_xsk_tx_metadata_ops,
++              xsk_tx_metadata_request(pool, &meta, &igc_xsk_tx_metadata_ops,
+                                       &meta_req);
+               /* xsk_tx_metadata_request() may have updated next_to_use */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+index dac5e9d4c8bdb..77ea51bfbaae5 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+@@ -505,7 +505,7 @@ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptx
+                */
+               mlx5e_xdp_mpwqe_session_start(sq);
+               if (meta)
+-                      xsk_tx_metadata_request(meta,
++                      xsk_tx_metadata_request(sq->xsk_pool, meta,
+                                               &mlx5e_xsk_tx_metadata_ops,
+                                               &session->wqe->eth);
+       }
+@@ -653,7 +653,8 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+       sq->pc += num_wqebbs;
+       if (meta)
+-              xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
++              xsk_tx_metadata_request(sq->xsk_pool, meta,
++                                      &mlx5e_xsk_tx_metadata_ops, eseg);
+       sq->doorbell_cseg = cseg;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 622f571b30350..b7e3f652501e4 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2748,8 +2748,8 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+               meta_req.set_ic = &set_ic;
+               meta_req.tbs = tx_q->tbs;
+               meta_req.edesc = &tx_q->dma_entx[entry];
+-              xsk_tx_metadata_request(&meta, &stmmac_xsk_tx_metadata_ops,
+-                                      &meta_req);
++              xsk_tx_metadata_request(pool, &meta,
++                                      &stmmac_xsk_tx_metadata_ops, &meta_req);
+               if (set_ic) {
+                       tx_q->tx_count_frames = 0;
+                       stmmac_set_tx_ic(priv, tx_desc);
+diff --git a/include/net/libeth/xsk.h b/include/net/libeth/xsk.h
+index e2fa6bf6b1b31..5dcc0d7f65b76 100644
+--- a/include/net/libeth/xsk.h
++++ b/include/net/libeth/xsk.h
+@@ -205,7 +205,7 @@ __libeth_xsk_xmit_fill_buf_md(const struct xdp_desc *xdesc,
+       BUILD_BUG_ON(!__builtin_constant_p(tmo == libeth_xsktmo));
+       tmo = tmo == libeth_xsktmo ? &__libeth_xsktmo : tmo;
+-      xsk_tx_metadata_request(&ctx.meta, tmo, &desc);
++      xsk_tx_metadata_request(sq->pool, &ctx.meta, tmo, &desc);
+       return desc;
+ }
+diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
+index f87c4215673ed..b344789f5df83 100644
+--- a/include/net/xdp_sock_drv.h
++++ b/include/net/xdp_sock_drv.h
+@@ -245,7 +245,7 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
+  * details.
+  *
+  * Return: new &xdp_desc_ctx struct containing desc's DMA address and metadata
+- * pointer, if it is present and valid (initialized to %NULL otherwise).
++ * pointer, if it is present (initialized to %NULL otherwise).
+  */
+ static inline struct xdp_desc_ctx
+ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+@@ -274,54 +274,56 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+ /**
+  *  xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission
+  *  and call appropriate xsk_tx_metadata_ops operation.
++ *  @pool: pointer to AF_XDP buffer pool, used to validate the metadata
+  *  @pmeta: pointer to pointer to AF_XDP metadata area
+  *  @ops: pointer to struct xsk_tx_metadata_ops
+- *  @priv: pointer to driver-private aread
++ *  @priv: pointer to driver-private area
+  *
+  *  This function should be called by the networking device when
+  *  it prepares AF_XDP egress packet.
+  */
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
++static inline void
++xsk_tx_metadata_request(const struct xsk_buff_pool *pool,
++                      struct xsk_tx_metadata **pmeta,
++                      const struct xsk_tx_metadata_ops *ops, void *priv)
+ {
+       const struct xsk_tx_metadata *meta = *pmeta;
++      u64 flags;
+       if (!meta)
+               return;
++      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags))) {
++              *pmeta = NULL;
++              return; /* no way to signal the error to the user */
++      }
++
+       if (ops->tmo_request_launch_time)
+-              if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
+-                      ops->tmo_request_launch_time(meta->request.launch_time,
+-                                                   priv);
++              if (flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
++                      ops->tmo_request_launch_time(
++                              READ_ONCE(meta->request.launch_time), priv);
+       if (ops->tmo_request_timestamp)
+-              if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP)
++              if (flags & XDP_TXMD_FLAGS_TIMESTAMP)
+                       ops->tmo_request_timestamp(priv);
+       if (ops->tmo_request_checksum)
+-              if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM)
+-                      ops->tmo_request_checksum(meta->request.csum_start,
+-                                                meta->request.csum_offset, priv);
++              if (flags & XDP_TXMD_FLAGS_CHECKSUM)
++                      ops->tmo_request_checksum(
++                              READ_ONCE(meta->request.csum_start),
++                              READ_ONCE(meta->request.csum_offset), priv);
+-      if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
++      if (!(flags & XDP_TXMD_FLAGS_TIMESTAMP))
+               *pmeta = NULL;
+ }
+ static inline struct xsk_tx_metadata *
+ __xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+ {
+-      struct xsk_tx_metadata *meta;
+-      u64 flags;
+-
+       if (!pool->tx_metadata_len)
+               return NULL;
+-      meta = data - pool->tx_metadata_len;
+-      if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
+-              return NULL; /* no way to signal the error to the user */
+-
+-      return meta;
++      return data - pool->tx_metadata_len;
+ }
+ static inline struct xsk_tx_metadata *
+@@ -520,9 +522,10 @@ xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
+       return false;
+ }
+-static inline void xsk_tx_metadata_request(struct xsk_tx_metadata **pmeta,
+-                                         const struct xsk_tx_metadata_ops *ops,
+-                                         void *priv)
++static inline void
++xsk_tx_metadata_request(const struct xsk_buff_pool *pool,
++                      struct xsk_tx_metadata **pmeta,
++                      const struct xsk_tx_metadata_ops *ops, void *priv)
+ {
+ }
+diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
+index 4538223f44082..f720422607771 100644
+--- a/net/xdp/xsk_buff_pool.c
++++ b/net/xdp/xsk_buff_pool.c
+@@ -765,11 +765,11 @@ EXPORT_SYMBOL(xp_raw_get_dma);
+  * @addr: desc address (from userspace)
+  *
+  * Helper for getting desc's DMA address and metadata pointer, if present.
+- * Saves one call on hotpath, double calculation of the actual address,
+- * and inline checks for metadata presence and sanity.
++ * Saves one call on hotpath and double calculation of the actual address.
++ * Metadata is validated later by xsk_tx_metadata_request().
+  *
+  * Return: new &xdp_desc_ctx struct containing desc's DMA address and metadata
+- * pointer, if it is present and valid (initialized to %NULL otherwise).
++ * pointer, if it is present (initialized to %NULL otherwise).
+  */
+ struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+ {
+-- 
+2.53.0
+