]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Tue, 9 Jun 2026 15:29:02 +0000 (11:29 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 9 Jun 2026 15:29:02 +0000 (11:29 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
294 files changed:
queue-5.10/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-5.10/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-5.10/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-5.10/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-5.10/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-5.10/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-5.10/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-5.10/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-5.10/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-5.10/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-5.10/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-5.10/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-5.10/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-5.10/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-5.10/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-5.10/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-5.10/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-5.10/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-5.15/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-5.15/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch [new file with mode: 0644]
queue-5.15/bluetooth-bnep-reject-short-frames-before-parsing.patch [new file with mode: 0644]
queue-5.15/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch [new file with mode: 0644]
queue-5.15/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-5.15/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-5.15/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch [new file with mode: 0644]
queue-5.15/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-5.15/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-5.15/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-5.15/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-5.15/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch [new file with mode: 0644]
queue-5.15/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-5.15/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-5.15/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-5.15/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-5.15/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-5.15/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-5.15/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-5.15/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-5.15/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-5.15/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-5.15/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-6.1/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-6.1/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch [new file with mode: 0644]
queue-6.1/bluetooth-bnep-reject-short-frames-before-parsing.patch [new file with mode: 0644]
queue-6.1/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch [new file with mode: 0644]
queue-6.1/bluetooth-mgmt-fix-backward-compatibility-with-users.patch [new file with mode: 0644]
queue-6.1/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-6.1/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-6.1/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch [new file with mode: 0644]
queue-6.1/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-6.1/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-6.1/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-6.1/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-6.1/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch [new file with mode: 0644]
queue-6.1/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-6.1/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-6.1/net-annotate-sk-sk_write_space-for-udp-sockmap.patch [new file with mode: 0644]
queue-6.1/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch [new file with mode: 0644]
queue-6.1/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-6.1/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-6.1/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-6.1/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-6.1/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-6.1/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-6.1/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-6.1/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch [new file with mode: 0644]
queue-6.1/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-6.1/ptp-vclock-switch-from-rcu-to-srcu.patch [new file with mode: 0644]
queue-6.1/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-6.1/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch [new file with mode: 0644]
queue-6.1/vxlan-vnifilter-send-notification-on-vni-add.patch [new file with mode: 0644]
queue-6.12/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-6.12/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch [new file with mode: 0644]
queue-6.12/bluetooth-bnep-reject-short-frames-before-parsing.patch [new file with mode: 0644]
queue-6.12/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch [new file with mode: 0644]
queue-6.12/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch [new file with mode: 0644]
queue-6.12/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch [new file with mode: 0644]
queue-6.12/bluetooth-iso-fix-not-using-bc_sid-as-advertisement-.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-fix-backward-compatibility-with-users.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-6.12/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-6.12/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch [new file with mode: 0644]
queue-6.12/devlink-release-nested-relation-on-devlink-free.patch [new file with mode: 0644]
queue-6.12/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-6.12/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-6.12/erofs-add-sysfs-node-to-drop-internal-caches.patch [new file with mode: 0644]
queue-6.12/erofs-fix-use-after-free-on-sbi-sync_decompress.patch [new file with mode: 0644]
queue-6.12/erofs-tidy-up-synchronous-decompression.patch [new file with mode: 0644]
queue-6.12/hsr-remove-warn_once-in-hsr_addr_is_self.patch [new file with mode: 0644]
queue-6.12/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-6.12/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-6.12/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch [new file with mode: 0644]
queue-6.12/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch [new file with mode: 0644]
queue-6.12/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch [new file with mode: 0644]
queue-6.12/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-6.12/net-annotate-sk-sk_write_space-for-udp-sockmap.patch [new file with mode: 0644]
queue-6.12/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch [new file with mode: 0644]
queue-6.12/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch [new file with mode: 0644]
queue-6.12/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-6.12/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-6.12/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-6.12/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch [new file with mode: 0644]
queue-6.12/net_sched-act_pedit-use-rcu-in-tcf_pedit_dump.patch [new file with mode: 0644]
queue-6.12/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-6.12/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-6.12/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch [new file with mode: 0644]
queue-6.12/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-6.12/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-6.12/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch [new file with mode: 0644]
queue-6.12/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch [new file with mode: 0644]
queue-6.12/octeontx2-pf-fix-ndc-sync-operation-errors.patch [new file with mode: 0644]
queue-6.12/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-6.12/ptp-vclock-switch-from-rcu-to-srcu.patch [new file with mode: 0644]
queue-6.12/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch [new file with mode: 0644]
queue-6.12/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-6.12/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch [new file with mode: 0644]
queue-6.12/vxlan-vnifilter-send-notification-on-vni-add.patch [new file with mode: 0644]
queue-6.12/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch [new file with mode: 0644]
queue-6.18/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-6.18/af_unix-fix-inq_len-update-problem-in-partial-read.patch [new file with mode: 0644]
queue-6.18/arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch [new file with mode: 0644]
queue-6.18/arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch [new file with mode: 0644]
queue-6.18/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch [new file with mode: 0644]
queue-6.18/bluetooth-bnep-reject-short-frames-before-parsing.patch [new file with mode: 0644]
queue-6.18/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch [new file with mode: 0644]
queue-6.18/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch [new file with mode: 0644]
queue-6.18/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch [new file with mode: 0644]
queue-6.18/bluetooth-mgmt-fix-backward-compatibility-with-users.patch [new file with mode: 0644]
queue-6.18/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-6.18/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-6.18/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch [new file with mode: 0644]
queue-6.18/bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch [new file with mode: 0644]
queue-6.18/devlink-release-nested-relation-on-devlink-free.patch [new file with mode: 0644]
queue-6.18/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-6.18/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-6.18/erofs-fix-use-after-free-on-sbi-sync_decompress.patch [new file with mode: 0644]
queue-6.18/erofs-tidy-up-synchronous-decompression.patch [new file with mode: 0644]
queue-6.18/hsr-remove-warn_once-in-hsr_addr_is_self.patch [new file with mode: 0644]
queue-6.18/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-6.18/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-6.18/ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch [new file with mode: 0644]
queue-6.18/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch [new file with mode: 0644]
queue-6.18/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-6.18/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch [new file with mode: 0644]
queue-6.18/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch [new file with mode: 0644]
queue-6.18/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-6.18/net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch [new file with mode: 0644]
queue-6.18/net-annotate-sk-sk_write_space-for-udp-sockmap.patch [new file with mode: 0644]
queue-6.18/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch [new file with mode: 0644]
queue-6.18/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch [new file with mode: 0644]
queue-6.18/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-6.18/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-6.18/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-6.18/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch [new file with mode: 0644]
queue-6.18/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-6.18/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-6.18/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch [new file with mode: 0644]
queue-6.18/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-6.18/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-6.18/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch [new file with mode: 0644]
queue-6.18/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch [new file with mode: 0644]
queue-6.18/octeontx2-pf-fix-ndc-sync-operation-errors.patch [new file with mode: 0644]
queue-6.18/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-6.18/ptp-vclock-switch-from-rcu-to-srcu.patch [new file with mode: 0644]
queue-6.18/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-6.18/sctp-validate-cached-peer-init-chunk-length-in-cooki.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch [new file with mode: 0644]
queue-6.18/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch [new file with mode: 0644]
queue-6.18/tee-fix-tee_ioctl_object_invoke_arg-padding.patch [new file with mode: 0644]
queue-6.18/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-6.18/tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch [new file with mode: 0644]
queue-6.18/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch [new file with mode: 0644]
queue-6.18/vxlan-vnifilter-send-notification-on-vni-add.patch [new file with mode: 0644]
queue-6.18/wifi-fix-leak-if-split-6-ghz-scanning-fails.patch [new file with mode: 0644]
queue-6.18/wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch [new file with mode: 0644]
queue-6.18/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch [new file with mode: 0644]
queue-6.18/xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch [new file with mode: 0644]
queue-6.6/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-6.6/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch [new file with mode: 0644]
queue-6.6/bluetooth-bnep-reject-short-frames-before-parsing.patch [new file with mode: 0644]
queue-6.6/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch [new file with mode: 0644]
queue-6.6/bluetooth-mgmt-fix-backward-compatibility-with-users.patch [new file with mode: 0644]
queue-6.6/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-6.6/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-6.6/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch [new file with mode: 0644]
queue-6.6/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-6.6/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-6.6/hsr-remove-warn_once-in-hsr_addr_is_self.patch [new file with mode: 0644]
queue-6.6/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-6.6/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-6.6/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch [new file with mode: 0644]
queue-6.6/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-6.6/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch [new file with mode: 0644]
queue-6.6/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-6.6/net-annotate-sk-sk_write_space-for-udp-sockmap.patch [new file with mode: 0644]
queue-6.6/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch [new file with mode: 0644]
queue-6.6/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch [new file with mode: 0644]
queue-6.6/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-6.6/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-6.6/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-6.6/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-6.6/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-6.6/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch [new file with mode: 0644]
queue-6.6/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-6.6/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-6.6/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch [new file with mode: 0644]
queue-6.6/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-6.6/ptp-vclock-switch-from-rcu-to-srcu.patch [new file with mode: 0644]
queue-6.6/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-6.6/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch [new file with mode: 0644]
queue-6.6/vxlan-vnifilter-send-notification-on-vni-add.patch [new file with mode: 0644]
queue-7.0/6lowpan-fix-off-by-one-in-multicast-context-address-.patch [new file with mode: 0644]
queue-7.0/af_unix-fix-inq_len-update-problem-in-partial-read.patch [new file with mode: 0644]
queue-7.0/arm-dts-gemini-fix-partition-offsets.patch [new file with mode: 0644]
queue-7.0/arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch [new file with mode: 0644]
queue-7.0/arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch [new file with mode: 0644]
queue-7.0/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch [new file with mode: 0644]
queue-7.0/bluetooth-bnep-reject-short-frames-before-parsing.patch [new file with mode: 0644]
queue-7.0/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch [new file with mode: 0644]
queue-7.0/bluetooth-iso-fix-a-use-after-free-of-the-hci_conn-p.patch [new file with mode: 0644]
queue-7.0/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch [new file with mode: 0644]
queue-7.0/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch [new file with mode: 0644]
queue-7.0/bluetooth-mgmt-fix-backward-compatibility-with-users.patch [new file with mode: 0644]
queue-7.0/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch [new file with mode: 0644]
queue-7.0/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch [new file with mode: 0644]
queue-7.0/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch [new file with mode: 0644]
queue-7.0/bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch [new file with mode: 0644]
queue-7.0/bonding-annotate-data-races-arcound-churn-variables.patch [new file with mode: 0644]
queue-7.0/devlink-release-nested-relation-on-devlink-free.patch [new file with mode: 0644]
queue-7.0/dm-cache-policy-smq-check-allocation-under-invalidat.patch [new file with mode: 0644]
queue-7.0/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch [new file with mode: 0644]
queue-7.0/erofs-fix-use-after-free-on-sbi-sync_decompress.patch [new file with mode: 0644]
queue-7.0/fwctl-bnxt_en-move-common-definitions-to-include-lin.patch [new file with mode: 0644]
queue-7.0/fwctl-bnxt_en-refactor-aux-bus-functions-to-be-more-.patch [new file with mode: 0644]
queue-7.0/geneve-fix-length-used-in-gro-hint-udp-checksum-adju.patch [new file with mode: 0644]
queue-7.0/hsr-remove-warn_once-in-hsr_addr_is_self.patch [new file with mode: 0644]
queue-7.0/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch [new file with mode: 0644]
queue-7.0/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch [new file with mode: 0644]
queue-7.0/ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch [new file with mode: 0644]
queue-7.0/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch [new file with mode: 0644]
queue-7.0/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch [new file with mode: 0644]
queue-7.0/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch [new file with mode: 0644]
queue-7.0/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch [new file with mode: 0644]
queue-7.0/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch [new file with mode: 0644]
queue-7.0/net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch [new file with mode: 0644]
queue-7.0/net-annotate-sk-sk_write_space-for-udp-sockmap.patch [new file with mode: 0644]
queue-7.0/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch [new file with mode: 0644]
queue-7.0/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch [new file with mode: 0644]
queue-7.0/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch [new file with mode: 0644]
queue-7.0/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch [new file with mode: 0644]
queue-7.0/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch [new file with mode: 0644]
queue-7.0/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch [new file with mode: 0644]
queue-7.0/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch [new file with mode: 0644]
queue-7.0/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch [new file with mode: 0644]
queue-7.0/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch [new file with mode: 0644]
queue-7.0/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch [new file with mode: 0644]
queue-7.0/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch [new file with mode: 0644]
queue-7.0/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch [new file with mode: 0644]
queue-7.0/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch [new file with mode: 0644]
queue-7.0/octeontx2-pf-fix-ndc-sync-operation-errors.patch [new file with mode: 0644]
queue-7.0/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch [new file with mode: 0644]
queue-7.0/ptp-vclock-switch-from-rcu-to-srcu.patch [new file with mode: 0644]
queue-7.0/reapply-bnxt_en-bring-back-rtnl_lock-in-the-bnxt_ope.patch [new file with mode: 0644]
queue-7.0/s390-bug-always-emit-format-word-in-__bug_entry.patch [new file with mode: 0644]
queue-7.0/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch [new file with mode: 0644]
queue-7.0/sctp-validate-cached-peer-init-chunk-length-in-cooki.patch [new file with mode: 0644]
queue-7.0/series
queue-7.0/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch [new file with mode: 0644]
queue-7.0/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch [new file with mode: 0644]
queue-7.0/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch [new file with mode: 0644]
queue-7.0/tee-fix-tee_ioctl_object_invoke_arg-padding.patch [new file with mode: 0644]
queue-7.0/tee-optee-prevent-use-after-free-when-the-client-exi.patch [new file with mode: 0644]
queue-7.0/tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch [new file with mode: 0644]
queue-7.0/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch [new file with mode: 0644]
queue-7.0/vxlan-vnifilter-send-notification-on-vni-add.patch [new file with mode: 0644]
queue-7.0/wifi-cfg80211-add-support-to-handle-incumbent-signal.patch [new file with mode: 0644]
queue-7.0/wifi-cfg80211-enforce-he-eht-cap-oper-consistency.patch [new file with mode: 0644]
queue-7.0/wifi-fix-leak-if-split-6-ghz-scanning-fails.patch [new file with mode: 0644]
queue-7.0/wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch [new file with mode: 0644]
queue-7.0/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch [new file with mode: 0644]
queue-7.0/wifi-nl80211-split-out-uhr-operation-information.patch [new file with mode: 0644]
queue-7.0/xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch [new file with mode: 0644]

diff --git a/queue-5.10/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-5.10/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..0ee1e96
--- /dev/null
@@ -0,0 +1,67 @@
+From 5c52e27970f6ba797ace203a91f9642f4f0f0fa7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index 52fad5dad9f715..d762c49e722fae 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-5.10/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-5.10/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..da9e9b1
--- /dev/null
@@ -0,0 +1,73 @@
+From 102c8c2e5f7c57eed03e98492211e84a3de1b761 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index b768abbf2b121a..3647e51d31062b 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -7364,6 +7364,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -7380,12 +7386,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-5.10/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-5.10/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..dec3762
--- /dev/null
@@ -0,0 +1,126 @@
+From 27ec0e481e2d63cadc82f117507cad3f7986b673 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index 2dcb70f49a68a5..faab36d54c5c5a 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -933,6 +943,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -946,6 +957,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       bh_lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -973,9 +989,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       bh_unlock_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-5.10/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..8f06af8
--- /dev/null
@@ -0,0 +1,71 @@
+From 73cda6fd16d981a07a3795de8a11734f0ae8ae8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index 95b0670c32acda..e5c4d7ff2c655b 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1585,18 +1585,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-5.10/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-5.10/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..dffb92d
--- /dev/null
@@ -0,0 +1,53 @@
+From d98a5e38fdac7819c91b15754475bf7af9e429f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index cd21905de580ff..d156cc60c3f4aa 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -164,6 +164,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -249,7 +250,9 @@ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-5.10/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-5.10/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..7b20c9b
--- /dev/null
@@ -0,0 +1,56 @@
+From 00df3310ed12fc676c5e7e7348ee5d26ded0ed99 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-5.10/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-5.10/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..09e1b0b
--- /dev/null
@@ -0,0 +1,54 @@
+From 273fc27cc2ef3363b93d1bcf1a8517892e84b8d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index da1b5038bdfd04..4afdaaab616239 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -543,6 +543,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-5.10/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-5.10/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..0b8f868
--- /dev/null
@@ -0,0 +1,127 @@
+From d2f7195ce52377f76e3585b6a25ee857ed166ec0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index c02c3bb0fe091d..7891c17ff8b688 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1396,8 +1396,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 4c9ef2ae4d6877..0805c9083eaa8f 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1417,7 +1417,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1479,9 +1479,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1489,6 +1488,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1545,7 +1548,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index d4903723be7e90..49b2e5d2b2c837 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-5.10/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..ec88c25
--- /dev/null
@@ -0,0 +1,79 @@
+From 4ff1ffb07e11f4a802ac3c0045c9bd1bcb86b784 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index c10a432a5b4351..017839c141841f 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -702,6 +702,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -752,6 +758,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-5.10/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..0753c64
--- /dev/null
@@ -0,0 +1,58 @@
+From aff237d0d358858dd8237da25666f69252b961d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index f6012f8e59f005..2c456b362621e6 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -452,7 +452,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-5.10/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..2e0103d
--- /dev/null
@@ -0,0 +1,99 @@
+From 02df86af6597091e0fdb3885710f541e0099c2ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 26a230c60efb70..f280fda24f7f07 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -799,6 +799,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -838,6 +868,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       ether_addr_copy(netdev->dev_addr, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 2a40cc827b1872..3062c54faffd18 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -118,6 +118,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-5.10/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-5.10/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..0a4c3dc
--- /dev/null
@@ -0,0 +1,106 @@
+From 51a5d4a931a07c68dc762d416e17c2edf3a79678 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index 2c88b8af3cdbe1..bbc4ab5e04f7d1 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -41,6 +41,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *act_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index bf98bb602a9de7..c724eea8cf8c52 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -93,11 +93,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -110,7 +105,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void tcf_action_cleanup(struct tc_action *p)
+-- 
+2.53.0
+
diff --git a/queue-5.10/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-5.10/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..a7c336e
--- /dev/null
@@ -0,0 +1,58 @@
+From 4daa3b40e6ee13d5a7031393a6f2321403f90d27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-5.10/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-5.10/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..d2e12da
--- /dev/null
@@ -0,0 +1,50 @@
+From 1983fb134edd72f163eef4ed21eb5de40c4989b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index 65b5b05fe38d37..24533bee001b7d 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -199,7 +199,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -213,7 +213,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-5.10/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-5.10/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..ce447e0
--- /dev/null
@@ -0,0 +1,113 @@
+From d502f5da6d6c84cde12899190c66894608216b7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 0a97b1a0f53e45..4a742dda15da71 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -21,6 +21,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -790,26 +792,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1214,27 +1221,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-5.10/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-5.10/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..1a64284
--- /dev/null
@@ -0,0 +1,41 @@
+From 0b715677a39b2e66b3b4ecc00fa4af9672736a67 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-5.10/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-5.10/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..8541467
--- /dev/null
@@ -0,0 +1,58 @@
+From 20a5fbb56e207ddf5452d119ab7754f5718017c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index f78daba60b35c0..ce5b8e6aa976f9 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1399,8 +1399,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1408,9 +1410,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.10/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-5.10/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..e7a0b75
--- /dev/null
@@ -0,0 +1,87 @@
+From 6e21075789b42bb03af8b9beb767d6b85be83e54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index af75b940855681..7ac3ad83ddd5fe 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2523,11 +2523,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
index 009d4e8bc6c43f105b7eaed0d4b922f9b7053edc..0916cf682e6006bb3fe44fb04523dddaf1ddd3c1 100644 (file)
@@ -127,3 +127,22 @@ hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch
 usb-serial-mct_u232-fix-memory-corruption-with-small.patch
 compiler-clang.h-add-__diag-infrastructure-for-clang.patch
 disable-wattribute-alias-for-clang-23-and-newer.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
diff --git a/queue-5.10/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-5.10/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..5dd6ec2
--- /dev/null
@@ -0,0 +1,287 @@
+From 936156aa94def542fd31e670379d7a6e5f35fee9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index d0f397c9024201..2386bbd38ce78b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-5.15/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..f0ab0ce
--- /dev/null
@@ -0,0 +1,67 @@
+From bff5b133340778a857c83761b3b1491a1e92fd5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index 52fad5dad9f715..d762c49e722fae 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-5.15/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch b/queue-5.15/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
new file mode 100644 (file)
index 0000000..24b2f7a
--- /dev/null
@@ -0,0 +1,71 @@
+From 5a25615f4b95f0196626c529cc94b9596cfd40ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 17:39:53 +0800
+Subject: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame()
+ extension handling
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+[ Upstream commit 72b8deccff17a7644e0367e1aaf1a36cfb014324 ]
+
+In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
+BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:
+
+1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
+   performs a native-endian read. The BNEP protocol specifies this field
+   in big-endian (network byte order), and the same file correctly uses
+   get_unaligned_be16() for the identical fields in
+   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().
+
+2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
+   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
+   entry), the filter extension length field already represents the total
+   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
+   which reads the same field as a byte count and divides by 4 to get
+   the number of filter entries.
+
+   The bogus * 2 means skb_pull advances twice as far as it should,
+   either dropping valid data from the next header or causing the pull
+   to fail entirely when the doubled length exceeds the remaining skb.
+
+Fix by splitting the pull into two steps: first use skb_pull_data() to
+safely pull and validate the 3-byte fixed header (ctrl type + length),
+then pull the variable-length data using the properly decoded length.
+
+Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index f3b9c1dee1bb61..1798069ce79149 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+                               goto badframe;
+                       break;
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET:
+-                      /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+-                      if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
++              case BNEP_FILTER_NET_TYPE_SET: {
++                      u8 *hdr;
++
++                      /* Pull ctrl type (1 b) + len (2 b) */
++                      hdr = skb_pull_data(skb, 3);
++                      if (!hdr)
++                              goto badframe;
++                      /* Pull data (len bytes); length is big-endian */
++                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+                               goto badframe;
+                       break;
++              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-5.15/bluetooth-bnep-reject-short-frames-before-parsing.patch b/queue-5.15/bluetooth-bnep-reject-short-frames-before-parsing.patch
new file mode 100644 (file)
index 0000000..5226192
--- /dev/null
@@ -0,0 +1,170 @@
+From 4a6979aa5d542aa4339426c11bb2543f2d85a34b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 11:22:09 +0800
+Subject: Bluetooth: bnep: reject short frames before parsing
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 6770d3a8acdf9151769180cc3710346c4cfbe6f0 ]
+
+A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
+packet type byte immediately and, for control packets, reads the control
+opcode and setup UUID-size byte before proving that those bytes are
+present. bnep_rx_control() also dereferences the control opcode without
+rejecting an empty control payload.
+
+Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
+return gates each dereference. Split the control handler so the frame
+path can pass an opcode that has already been pulled, and keep the
+byte-buffer wrapper for extension control payloads.
+
+For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
+setup payload. struct bnep_setup_conn_req carries destination and source
+service UUIDs after that byte, each uuid_size bytes, so the parser now
+documents that tuple explicitly instead of leaving the pull length as an
+opaque multiplication.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
+The buggy address belongs to the object at ffff88800c0f7908 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 1-byte
+region [ffff88800c0f7908, ffff88800c0f7909)
+Read of size 1
+Call trace:
+  dump_stack_lvl+0xb3/0x140 (?:?)
+  print_address_description+0x57/0x3a0 (?:?)
+  bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
+  print_report+0xb9/0x2b0 (?:?)
+  __virt_addr_valid+0x1ba/0x3a0 (?:?)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  kasan_addr_to_slab+0x21/0x60 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
+  worker_thread+0x65c/0xe40 (?:?)
+  __kthread_parkme+0x184/0x230 (?:?)
+  kthread+0x35e/0x470 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  ret_from_fork+0x586/0x870 (?:?)
+  __switch_to+0x74f/0xdc0 (?:?)
+  ret_from_fork_asm+0x1a/0x30 (?:?)
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index 1798069ce79149..627ce3de29c8ee 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
+       return 0;
+ }
+-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
++                             int len)
+ {
+-      u8  cmd = *(u8 *)data;
+       int err = 0;
+-      data++;
+-      len--;
+-
+       switch (cmd) {
+       case BNEP_CMD_NOT_UNDERSTOOD:
+       case BNEP_SETUP_CONN_RSP:
+@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+       return err;
+ }
++static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++{
++      if (len < 1)
++              return -EILSEQ;
++
++      return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
++}
++
+ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct bnep_ext_hdr *h;
+@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct net_device *dev = s->dev;
+       struct sk_buff *nskb;
++      u8 *data;
+       u8 type, ctrl_type;
+       dev->stats.rx_bytes += skb->len;
+-      type = *(u8 *) skb->data;
+-      skb_pull(skb, 1);
+-      ctrl_type = *(u8 *)skb->data;
++      data = skb_pull_data(skb, sizeof(type));
++      if (!data)
++              goto badframe;
++      type = *data;
+       if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
+               goto badframe;
+       if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
+-              if (bnep_rx_control(s, skb->data, skb->len) < 0) {
++              data = skb_pull_data(skb, sizeof(ctrl_type));
++              if (!data)
++                      goto badframe;
++              ctrl_type = *data;
++
++              if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
+                       dev->stats.tx_errors++;
+                       kfree_skb(skb);
+                       return 0;
+@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+               /* Verify and pull ctrl message since it's already processed */
+               switch (ctrl_type) {
+-              case BNEP_SETUP_CONN_REQ:
+-                      /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+-                      if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
++              case BNEP_SETUP_CONN_REQ: {
++                      u8 uuid_size;
++
++                      /* Pull uuid_size and the dst/src service UUIDs. */
++                      data = skb_pull_data(skb, sizeof(uuid_size));
++                      if (!data)
++                              goto badframe;
++                      uuid_size = *data;
++                      if (!skb_pull(skb, uuid_size + uuid_size))
+                               goto badframe;
+                       break;
++              }
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET: {
+-                      u8 *hdr;
+-
+-                      /* Pull ctrl type (1 b) + len (2 b) */
+-                      hdr = skb_pull_data(skb, 3);
+-                      if (!hdr)
++              case BNEP_FILTER_NET_TYPE_SET:
++                      /* Pull: len (2 b), data (len bytes) */
++                      data = skb_pull_data(skb, sizeof(u16));
++                      if (!data)
+                               goto badframe;
+-                      /* Pull data (len bytes); length is big-endian */
+-                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
++                      if (!skb_pull(skb, get_unaligned_be16(data)))
+                               goto badframe;
+                       break;
+-              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-5.15/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch b/queue-5.15/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
new file mode 100644 (file)
index 0000000..5aac30a
--- /dev/null
@@ -0,0 +1,58 @@
+From 827605a6e1bfc878959df59247decd4b229877f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 08:54:26 +0530
+Subject: Bluetooth: fix memory leak in error path of hci_alloc_dev()
+
+From: Bharath Reddy <kbreddy.rpbc@gmail.com>
+
+[ Upstream commit 37b3009bf5976e8ab77c8b9a9bc3bbd7ff49e37f ]
+
+Early failures in Bluetooth HCI UART configuration leak SRCU percpu
+memory.
+
+When device initialization fails before hci_register_dev() completes,
+the HCI_UNREGISTER flag is never set. As a result, when the device
+reference count reaches zero, bt_host_release() evaluates this flag as
+false and falls back to a direct kfree(hdev).
+
+Because hci_release_dev() is bypassed, the SRCU struct initialized
+early in hci_alloc_dev() is never cleaned up, resulting in a leak of
+percpu memory.
+
+Fix the leak by explicitly calling cleanup_srcu_struct() in the
+fallback (unregistered) branch of bt_host_release() before freeing
+the device.
+
+Reported-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=535ecc844591e50588a5
+Tested-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Fixes: 1d6123102e9f ("Bluetooth: hci_core: Fix use-after-free in vhci_flush()")
+Signed-off-by: Bharath Reddy <kbreddy.rpbc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sysfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
+index cc7d4a8ed8ce24..b1886e517a78bc 100644
+--- a/net/bluetooth/hci_sysfs.c
++++ b/net/bluetooth/hci_sysfs.c
+@@ -81,10 +81,12 @@ static void bt_host_release(struct device *dev)
+ {
+       struct hci_dev *hdev = to_hci_dev(dev);
+-      if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
++      if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_release_dev(hdev);
+-      else
++      } else {
++              cleanup_srcu_struct(&hdev->srcu);
+               kfree(hdev);
++      }
+       module_put(THIS_MODULE);
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-5.15/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..86fe9b3
--- /dev/null
@@ -0,0 +1,73 @@
+From cfcda54752d4bae174baa4b89c2e45740a4a4d13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 09232c424446bc..337c3cb8eec589 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -7635,6 +7635,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -7651,12 +7657,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-5.15/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-5.15/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..2a309a0
--- /dev/null
@@ -0,0 +1,126 @@
+From 823f31595bde989177539441c4999a358f968365 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index d1f2c936a8a811..2f091f134a606c 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -941,6 +951,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -954,6 +965,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -981,9 +997,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       release_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch b/queue-5.15/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
new file mode 100644 (file)
index 0000000..dd804d2
--- /dev/null
@@ -0,0 +1,167 @@
+From b9f42e89077b115bc15c205ead2af447593cb32a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:04:43 +0900
+Subject: Bluetooth: RFCOMM: validate skb length in MCC handlers
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 23882b828c3c8c51d0c946446a396b10abb3b16b ]
+
+The RFCOMM MCC handlers cast skb->data to protocol-specific structs
+without validating skb->len first. A malicious remote device can send
+truncated MCC frames and trigger out-of-bounds reads in these handlers.
+
+Fix this by using skb_pull_data() to validate and access the required
+data before dereferencing it.
+
+rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
+1-byte RPN requests. Handle this by validating only the DLCI byte first,
+and validating the full struct only when len > 1.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
+ 1 file changed, 49 insertions(+), 18 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
+index 4f54c7df3a94f8..374187def190da 100644
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -1427,10 +1427,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
+ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_pn *pn = (void *) skb->data;
++      struct rfcomm_pn *pn;
+       struct rfcomm_dlc *d;
+-      u8 dlci = pn->dlci;
++      u8 dlci;
++
++      pn = skb_pull_data(skb, sizeof(*pn));
++      if (!pn)
++              return -EILSEQ;
++      dlci = pn->dlci;
+       BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
+       if (!dlci)
+@@ -1479,8 +1484,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
+ {
+-      struct rfcomm_rpn *rpn = (void *) skb->data;
+-      u8 dlci = __get_dlci(rpn->dlci);
++      struct rfcomm_rpn *rpn;
++      u8 dlci;
+       u8 bit_rate  = 0;
+       u8 data_bits = 0;
+@@ -1491,15 +1496,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+       u8 xoff_char = 0;
+       u16 rpn_mask = RFCOMM_RPN_PM_ALL;
+-      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+-              dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+-              rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++      if (len == 1) {
++              rpn = skb_pull_data(skb, 1);
++              if (!rpn)
++                      return -EILSEQ;
+-      if (!cr)
+-              return 0;
++              dlci = __get_dlci(rpn->dlci);
++
++              if (!cr)
++                      return 0;
+-      if (len == 1) {
+-              /* This is a request, return default (according to ETSI TS 07.10) settings */
+               bit_rate  = RFCOMM_RPN_BR_9600;
+               data_bits = RFCOMM_RPN_DATA_8;
+               stop_bits = RFCOMM_RPN_STOP_1;
+@@ -1510,6 +1516,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+               goto rpn_out;
+       }
++      rpn = skb_pull_data(skb, sizeof(*rpn));
++      if (!rpn)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rpn->dlci);
++
++      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
++             dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
++             rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++
++      if (!cr)
++              return 0;
++
+       /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+        * no parity, no flow control lines, normal XON/XOFF chars */
+@@ -1585,9 +1604,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_rls *rls = (void *) skb->data;
+-      u8 dlci = __get_dlci(rls->dlci);
++      struct rfcomm_rls *rls;
++      u8 dlci;
++      rls = skb_pull_data(skb, sizeof(*rls));
++      if (!rls)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rls->dlci);
+       BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+       if (!cr)
+@@ -1604,10 +1628,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_msc *msc = (void *) skb->data;
++      struct rfcomm_msc *msc;
+       struct rfcomm_dlc *d;
+-      u8 dlci = __get_dlci(msc->dlci);
++      u8 dlci;
++
++      msc = skb_pull_data(skb, sizeof(*msc));
++      if (!msc)
++              return -EILSEQ;
++      dlci = __get_dlci(msc->dlci);
+       BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
+       d = rfcomm_dlc_get(s, dlci);
+@@ -1640,17 +1669,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
+ {
+-      struct rfcomm_mcc *mcc = (void *) skb->data;
++      struct rfcomm_mcc *mcc;
+       u8 type, cr, len;
++      mcc = skb_pull_data(skb, sizeof(*mcc));
++      if (!mcc)
++              return -EILSEQ;
++
+       cr   = __test_cr(mcc->type);
+       type = __get_mcc_type(mcc->type);
+       len  = __get_mcc_len(mcc->len);
+       BT_DBG("%p type 0x%x cr %d", s, type, cr);
+-      skb_pull(skb, 2);
+-
+       switch (type) {
+       case RFCOMM_PN:
+               rfcomm_recv_pn(s, cr, skb);
+-- 
+2.53.0
+
diff --git a/queue-5.15/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-5.15/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..e08d713
--- /dev/null
@@ -0,0 +1,71 @@
+From 2e14f447082e7619f48366f631a01ca68c121548 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index 95b0670c32acda..e5c4d7ff2c655b 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1585,18 +1585,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-5.15/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-5.15/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..c66e3fd
--- /dev/null
@@ -0,0 +1,53 @@
+From 0c828af00c5388a4285ac63070e62e4d35fd9663 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index 47852b9dd5eaa2..d2a89a99bd71cf 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -166,6 +166,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-5.15/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-5.15/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..f95e891
--- /dev/null
@@ -0,0 +1,56 @@
+From dd7e6eb119c3ea13d06d48b4c37667e1e343a7af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-5.15/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-5.15/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..22db80f
--- /dev/null
@@ -0,0 +1,54 @@
+From 29696ef7caf95a71c3f3e7c372d0750e77a5ce51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index da1b5038bdfd04..4afdaaab616239 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -543,6 +543,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-5.15/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch b/queue-5.15/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
new file mode 100644 (file)
index 0000000..57ee14e
--- /dev/null
@@ -0,0 +1,107 @@
+From b9869d1ed6d30a63dc017f9a20f9b54491a7754e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 13:18:11 +0300
+Subject: ipv6: mcast: Fix use-after-free when processing MLD queries
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ]
+
+When processing an MLD query, a pointer to the multicast group address
+is retrieved when initially parsing the packet. This pointer is later
+dereferenced without being reloaded despite the fact that the skb header
+might have been reallocated following the pskb_may_pull() calls, leading
+to a use-after-free [1].
+
+Fix by copying the multicast group address when the packet is initially
+parsed.
+
+[1]
+BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512)
+Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
+
+Workqueue: mld mld_query_work
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+print_address_description.constprop.0 (mm/kasan/report.c:378)
+print_report (mm/kasan/report.c:482)
+kasan_report (mm/kasan/report.c:595)
+__mld_query_work (net/ipv6/mcast.c:1512)
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+</TASK>
+
+[...]
+
+Freed by task 118:
+kasan_save_stack (mm/kasan/common.c:57)
+kasan_save_track (mm/kasan/common.c:78)
+kasan_save_free_info (mm/kasan/generic.c:584)
+__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
+kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566)
+pskb_expand_head (net/core/skbuff.c:2335)
+__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4))
+__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+
+Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Reviewed-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/mcast.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index 77a9f17c816b5d..18a3516abb586e 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1392,9 +1392,9 @@ void igmp6_event_query(struct sk_buff *skb)
+ static void __mld_query_work(struct sk_buff *skb)
+ {
+       struct mld2_query *mlh2 = NULL;
+-      const struct in6_addr *group;
+       unsigned long max_delay;
+       struct inet6_dev *idev;
++      struct in6_addr group;
+       struct ifmcaddr6 *ma;
+       struct mld_msg *mld;
+       int group_type;
+@@ -1426,8 +1426,8 @@ static void __mld_query_work(struct sk_buff *skb)
+               goto kfree_skb;
+       mld = (struct mld_msg *)icmp6_hdr(skb);
+-      group = &mld->mld_mca;
+-      group_type = ipv6_addr_type(group);
++      group = mld->mld_mca;
++      group_type = ipv6_addr_type(&group);
+       if (group_type != IPV6_ADDR_ANY &&
+           !(group_type&IPV6_ADDR_MULTICAST))
+@@ -1477,7 +1477,7 @@ static void __mld_query_work(struct sk_buff *skb)
+               }
+       } else {
+               for_each_mc_mclock(idev, ma) {
+-                      if (!ipv6_addr_equal(group, &ma->mca_addr))
++                      if (!ipv6_addr_equal(&group, &ma->mca_addr))
+                               continue;
+                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                               /* gsquery <- gsquery && mark */
+-- 
+2.53.0
+
diff --git a/queue-5.15/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-5.15/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..e4c9177
--- /dev/null
@@ -0,0 +1,127 @@
+From 3c989e329a03c95f1dd4708583193a8e9be00dbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 59f8412de45ac4..41e20b7e8e88db 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1396,8 +1396,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 4c9ef2ae4d6877..0805c9083eaa8f 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1417,7 +1417,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1479,9 +1479,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1489,6 +1488,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1545,7 +1548,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index d4903723be7e90..49b2e5d2b2c837 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-5.15/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..9cea4bf
--- /dev/null
@@ -0,0 +1,79 @@
+From 06ded69c972add69866c41b515b86439c680c5d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index c10a432a5b4351..017839c141841f 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -702,6 +702,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -752,6 +758,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-5.15/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..aa1b97a
--- /dev/null
@@ -0,0 +1,58 @@
+From 5c7a3d4fef94a9abfb3734d9e32d80a5003cc4bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index f6012f8e59f005..2c456b362621e6 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -452,7 +452,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-5.15/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..7875e4d
--- /dev/null
@@ -0,0 +1,99 @@
+From 5dfabbaf1f62630af1161648744ceab79a790141 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 49d40685136d46..8db83741aaa570 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -792,6 +792,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -831,6 +861,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       eth_hw_addr_set(netdev, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index a1226ab0fb4217..40351d38299aac 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -118,6 +118,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-5.15/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-5.15/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..289575c
--- /dev/null
@@ -0,0 +1,106 @@
+From cfb7a199cf50630100b0a7517d861e724429c06e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index ab67d62ff31784..29d5dc201b5cc5 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -41,6 +41,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *act_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index 0b4deb33bdf7ad..20944a2e162e7f 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -109,11 +109,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -126,7 +121,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void tcf_action_cleanup(struct tc_action *p)
+-- 
+2.53.0
+
diff --git a/queue-5.15/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-5.15/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..139e7f1
--- /dev/null
@@ -0,0 +1,58 @@
+From 5a65db59beda62bcac8ad1f3f3f905bcbd4e6c1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-5.15/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-5.15/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..4e6b513
--- /dev/null
@@ -0,0 +1,50 @@
+From d0a361e8d7b9c43fb4d1e4242c3b30007a52cd9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index 159e1e4441a433..7a0c645a11c390 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -202,7 +202,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -216,7 +216,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-5.15/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-5.15/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..7702d4c
--- /dev/null
@@ -0,0 +1,113 @@
+From fc549900783654782236c2d05a99c966c30c31f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index cdb2c3e23af7ee..91d3e3eea1be0b 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -21,6 +21,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -790,26 +792,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1214,27 +1221,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-5.15/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-5.15/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..e8ace3c
--- /dev/null
@@ -0,0 +1,41 @@
+From 7ce66bd586341862d360969ad74af0b1b71ac2e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-5.15/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-5.15/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..f37834b
--- /dev/null
@@ -0,0 +1,58 @@
+From 61dc5c7f56fe563e757944560e510bc00e3d13e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 70d76fdb9f569d..58a59b2d70cf2b 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1399,8 +1399,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1408,9 +1410,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-5.15/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-5.15/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..2ac5fe1
--- /dev/null
@@ -0,0 +1,87 @@
+From 149b109f714a30308d37d39c3184ac87704eecea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 2f9f24b1885208..3ca6b7b81124ff 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2583,11 +2583,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
index 01ae3f292b06f1b7e9018ab12dd6ade48cc6f17b..7ac33f63f3eed15b9450ae66f1cbff15e0ed6697 100644 (file)
@@ -144,3 +144,27 @@ bpf-free-reuseport-cbpf-prog-after-rcu-grace-period.patch
 usb-serial-mct_u232-fix-memory-corruption-with-small.patch
 compiler-clang.h-add-__diag-infrastructure-for-clang.patch
 disable-wattribute-alias-for-clang-23-and-newer.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
+bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
+bluetooth-bnep-reject-short-frames-before-parsing.patch
+bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
diff --git a/queue-5.15/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-5.15/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..9537929
--- /dev/null
@@ -0,0 +1,287 @@
+From 3fbd7242b71fd460f8688becdd59db0e7a62fb07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index d0f397c9024201..2386bbd38ce78b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-6.1/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..272688f
--- /dev/null
@@ -0,0 +1,67 @@
+From 8a4b969af3cec9a03083f52d2a6a12c9d56e4b3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index 52fad5dad9f715..d762c49e722fae 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch b/queue-6.1/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
new file mode 100644 (file)
index 0000000..fd7731f
--- /dev/null
@@ -0,0 +1,71 @@
+From 7c4397588a208c6d9440401b3b9a97c27cc695ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 17:39:53 +0800
+Subject: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame()
+ extension handling
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+[ Upstream commit 72b8deccff17a7644e0367e1aaf1a36cfb014324 ]
+
+In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
+BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:
+
+1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
+   performs a native-endian read. The BNEP protocol specifies this field
+   in big-endian (network byte order), and the same file correctly uses
+   get_unaligned_be16() for the identical fields in
+   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().
+
+2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
+   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
+   entry), the filter extension length field already represents the total
+   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
+   which reads the same field as a byte count and divides by 4 to get
+   the number of filter entries.
+
+   The bogus * 2 means skb_pull advances twice as far as it should,
+   either dropping valid data from the next header or causing the pull
+   to fail entirely when the doubled length exceeds the remaining skb.
+
+Fix by splitting the pull into two steps: first use skb_pull_data() to
+safely pull and validate the 3-byte fixed header (ctrl type + length),
+then pull the variable-length data using the properly decoded length.
+
+Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index e125afe573fcf2..9d804b08de88e0 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+                               goto badframe;
+                       break;
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET:
+-                      /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+-                      if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
++              case BNEP_FILTER_NET_TYPE_SET: {
++                      u8 *hdr;
++
++                      /* Pull ctrl type (1 b) + len (2 b) */
++                      hdr = skb_pull_data(skb, 3);
++                      if (!hdr)
++                              goto badframe;
++                      /* Pull data (len bytes); length is big-endian */
++                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+                               goto badframe;
+                       break;
++              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-bnep-reject-short-frames-before-parsing.patch b/queue-6.1/bluetooth-bnep-reject-short-frames-before-parsing.patch
new file mode 100644 (file)
index 0000000..2d29a61
--- /dev/null
@@ -0,0 +1,170 @@
+From 70401fc75bec46315758eed90c9c47837af2b376 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 11:22:09 +0800
+Subject: Bluetooth: bnep: reject short frames before parsing
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 6770d3a8acdf9151769180cc3710346c4cfbe6f0 ]
+
+A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
+packet type byte immediately and, for control packets, reads the control
+opcode and setup UUID-size byte before proving that those bytes are
+present. bnep_rx_control() also dereferences the control opcode without
+rejecting an empty control payload.
+
+Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
+return gates each dereference. Split the control handler so the frame
+path can pass an opcode that has already been pulled, and keep the
+byte-buffer wrapper for extension control payloads.
+
+For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
+setup payload. struct bnep_setup_conn_req carries destination and source
+service UUIDs after that byte, each uuid_size bytes, so the parser now
+documents that tuple explicitly instead of leaving the pull length as an
+opaque multiplication.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
+The buggy address belongs to the object at ffff88800c0f7908 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 1-byte
+region [ffff88800c0f7908, ffff88800c0f7909)
+Read of size 1
+Call trace:
+  dump_stack_lvl+0xb3/0x140 (?:?)
+  print_address_description+0x57/0x3a0 (?:?)
+  bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
+  print_report+0xb9/0x2b0 (?:?)
+  __virt_addr_valid+0x1ba/0x3a0 (?:?)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  kasan_addr_to_slab+0x21/0x60 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
+  worker_thread+0x65c/0xe40 (?:?)
+  __kthread_parkme+0x184/0x230 (?:?)
+  kthread+0x35e/0x470 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  ret_from_fork+0x586/0x870 (?:?)
+  __switch_to+0x74f/0xdc0 (?:?)
+  ret_from_fork_asm+0x1a/0x30 (?:?)
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index 9d804b08de88e0..45d0f84652fc60 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
+       return 0;
+ }
+-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
++                             int len)
+ {
+-      u8  cmd = *(u8 *)data;
+       int err = 0;
+-      data++;
+-      len--;
+-
+       switch (cmd) {
+       case BNEP_CMD_NOT_UNDERSTOOD:
+       case BNEP_SETUP_CONN_RSP:
+@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+       return err;
+ }
++static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++{
++      if (len < 1)
++              return -EILSEQ;
++
++      return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
++}
++
+ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct bnep_ext_hdr *h;
+@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct net_device *dev = s->dev;
+       struct sk_buff *nskb;
++      u8 *data;
+       u8 type, ctrl_type;
+       dev->stats.rx_bytes += skb->len;
+-      type = *(u8 *) skb->data;
+-      skb_pull(skb, 1);
+-      ctrl_type = *(u8 *)skb->data;
++      data = skb_pull_data(skb, sizeof(type));
++      if (!data)
++              goto badframe;
++      type = *data;
+       if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
+               goto badframe;
+       if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
+-              if (bnep_rx_control(s, skb->data, skb->len) < 0) {
++              data = skb_pull_data(skb, sizeof(ctrl_type));
++              if (!data)
++                      goto badframe;
++              ctrl_type = *data;
++
++              if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
+                       dev->stats.tx_errors++;
+                       kfree_skb(skb);
+                       return 0;
+@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+               /* Verify and pull ctrl message since it's already processed */
+               switch (ctrl_type) {
+-              case BNEP_SETUP_CONN_REQ:
+-                      /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+-                      if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
++              case BNEP_SETUP_CONN_REQ: {
++                      u8 uuid_size;
++
++                      /* Pull uuid_size and the dst/src service UUIDs. */
++                      data = skb_pull_data(skb, sizeof(uuid_size));
++                      if (!data)
++                              goto badframe;
++                      uuid_size = *data;
++                      if (!skb_pull(skb, uuid_size + uuid_size))
+                               goto badframe;
+                       break;
++              }
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET: {
+-                      u8 *hdr;
+-
+-                      /* Pull ctrl type (1 b) + len (2 b) */
+-                      hdr = skb_pull_data(skb, 3);
+-                      if (!hdr)
++              case BNEP_FILTER_NET_TYPE_SET:
++                      /* Pull: len (2 b), data (len bytes) */
++                      data = skb_pull_data(skb, sizeof(u16));
++                      if (!data)
+                               goto badframe;
+-                      /* Pull data (len bytes); length is big-endian */
+-                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
++                      if (!skb_pull(skb, get_unaligned_be16(data)))
+                               goto badframe;
+                       break;
+-              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch b/queue-6.1/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
new file mode 100644 (file)
index 0000000..c5344df
--- /dev/null
@@ -0,0 +1,58 @@
+From f0b025f60ade21d989143d75ac3a0a75df167365 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 08:54:26 +0530
+Subject: Bluetooth: fix memory leak in error path of hci_alloc_dev()
+
+From: Bharath Reddy <kbreddy.rpbc@gmail.com>
+
+[ Upstream commit 37b3009bf5976e8ab77c8b9a9bc3bbd7ff49e37f ]
+
+Early failures in Bluetooth HCI UART configuration leak SRCU percpu
+memory.
+
+When device initialization fails before hci_register_dev() completes,
+the HCI_UNREGISTER flag is never set. As a result, when the device
+reference count reaches zero, bt_host_release() evaluates this flag as
+false and falls back to a direct kfree(hdev).
+
+Because hci_release_dev() is bypassed, the SRCU struct initialized
+early in hci_alloc_dev() is never cleaned up, resulting in a leak of
+percpu memory.
+
+Fix the leak by explicitly calling cleanup_srcu_struct() in the
+fallback (unregistered) branch of bt_host_release() before freeing
+the device.
+
+Reported-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=535ecc844591e50588a5
+Tested-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Fixes: 1d6123102e9f ("Bluetooth: hci_core: Fix use-after-free in vhci_flush()")
+Signed-off-by: Bharath Reddy <kbreddy.rpbc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sysfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
+index cc7d4a8ed8ce24..b1886e517a78bc 100644
+--- a/net/bluetooth/hci_sysfs.c
++++ b/net/bluetooth/hci_sysfs.c
+@@ -81,10 +81,12 @@ static void bt_host_release(struct device *dev)
+ {
+       struct hci_dev *hdev = to_hci_dev(dev);
+-      if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
++      if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_release_dev(hdev);
+-      else
++      } else {
++              cleanup_srcu_struct(&hdev->srcu);
+               kfree(hdev);
++      }
+       module_put(THIS_MODULE);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-mgmt-fix-backward-compatibility-with-users.patch b/queue-6.1/bluetooth-mgmt-fix-backward-compatibility-with-users.patch
new file mode 100644 (file)
index 0000000..792fd57
--- /dev/null
@@ -0,0 +1,43 @@
+From aa1c286988ac33439a2b6190c7f476df01d22f40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:48:34 -0400
+Subject: Bluetooth: MGMT: Fix backward compatibility with userspace
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 149324fc762c2a7acef9c26790566f81f475e51f ]
+
+bluetoothd has a bug with makes it send extra bytes as part of
+MGMT_OP_ADD_EXT_ADV_DATA which are now being checked to be the
+exact the expected length, relax this so only when the expected
+length is greater than the data length to cause an error since
+that would result in accessing invalid memory, otherwise just
+ignore the extra bytes.
+
+Link: https://lore.kernel.org/linux-bluetooth/20260602204749.210857-1-luiz.dentz@gmail.com/T/#u
+Fixes: d3f7d17960ed ("Bluetooth: MGMT: validate Add Extended Advertising Data length")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index cc058c77d2e252..cd494f5ebb4dba 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -9079,8 +9079,9 @@ static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data,
+       BT_DBG("%s", hdev->name);
+-      expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len);
+-      if (expected_len != data_len)
++      expected_len = struct_size(cp, data, cp->adv_data_len +
++                                 cp->scan_rsp_len);
++      if (expected_len > data_len)
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
+                                      MGMT_STATUS_INVALID_PARAMS);
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-6.1/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..a11a1b1
--- /dev/null
@@ -0,0 +1,73 @@
+From 6d190e55eb8884130a2eda3da4ee17ebcdadc38e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index dd7d12418e0738..cc058c77d2e252 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -8602,6 +8602,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -8618,12 +8624,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-6.1/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..3f5aba0
--- /dev/null
@@ -0,0 +1,126 @@
+From bd1c3678dda8f848d01c109d930b87d2f1bddf3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index bc2b22c2b3aec7..d72cdcd2e2bb11 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -941,6 +951,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -954,6 +965,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -981,9 +997,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       release_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch b/queue-6.1/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
new file mode 100644 (file)
index 0000000..9404629
--- /dev/null
@@ -0,0 +1,167 @@
+From 4f6ba19c8386a6022120a6ca3e95bce04cee0f03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:04:43 +0900
+Subject: Bluetooth: RFCOMM: validate skb length in MCC handlers
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 23882b828c3c8c51d0c946446a396b10abb3b16b ]
+
+The RFCOMM MCC handlers cast skb->data to protocol-specific structs
+without validating skb->len first. A malicious remote device can send
+truncated MCC frames and trigger out-of-bounds reads in these handlers.
+
+Fix this by using skb_pull_data() to validate and access the required
+data before dereferencing it.
+
+rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
+1-byte RPN requests. Handle this by validating only the DLCI byte first,
+and validating the full struct only when len > 1.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
+ 1 file changed, 49 insertions(+), 18 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
+index 4f54c7df3a94f8..374187def190da 100644
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -1427,10 +1427,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
+ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_pn *pn = (void *) skb->data;
++      struct rfcomm_pn *pn;
+       struct rfcomm_dlc *d;
+-      u8 dlci = pn->dlci;
++      u8 dlci;
++
++      pn = skb_pull_data(skb, sizeof(*pn));
++      if (!pn)
++              return -EILSEQ;
++      dlci = pn->dlci;
+       BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
+       if (!dlci)
+@@ -1479,8 +1484,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
+ {
+-      struct rfcomm_rpn *rpn = (void *) skb->data;
+-      u8 dlci = __get_dlci(rpn->dlci);
++      struct rfcomm_rpn *rpn;
++      u8 dlci;
+       u8 bit_rate  = 0;
+       u8 data_bits = 0;
+@@ -1491,15 +1496,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+       u8 xoff_char = 0;
+       u16 rpn_mask = RFCOMM_RPN_PM_ALL;
+-      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+-              dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+-              rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++      if (len == 1) {
++              rpn = skb_pull_data(skb, 1);
++              if (!rpn)
++                      return -EILSEQ;
+-      if (!cr)
+-              return 0;
++              dlci = __get_dlci(rpn->dlci);
++
++              if (!cr)
++                      return 0;
+-      if (len == 1) {
+-              /* This is a request, return default (according to ETSI TS 07.10) settings */
+               bit_rate  = RFCOMM_RPN_BR_9600;
+               data_bits = RFCOMM_RPN_DATA_8;
+               stop_bits = RFCOMM_RPN_STOP_1;
+@@ -1510,6 +1516,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+               goto rpn_out;
+       }
++      rpn = skb_pull_data(skb, sizeof(*rpn));
++      if (!rpn)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rpn->dlci);
++
++      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
++             dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
++             rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++
++      if (!cr)
++              return 0;
++
+       /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+        * no parity, no flow control lines, normal XON/XOFF chars */
+@@ -1585,9 +1604,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_rls *rls = (void *) skb->data;
+-      u8 dlci = __get_dlci(rls->dlci);
++      struct rfcomm_rls *rls;
++      u8 dlci;
++      rls = skb_pull_data(skb, sizeof(*rls));
++      if (!rls)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rls->dlci);
+       BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+       if (!cr)
+@@ -1604,10 +1628,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_msc *msc = (void *) skb->data;
++      struct rfcomm_msc *msc;
+       struct rfcomm_dlc *d;
+-      u8 dlci = __get_dlci(msc->dlci);
++      u8 dlci;
++
++      msc = skb_pull_data(skb, sizeof(*msc));
++      if (!msc)
++              return -EILSEQ;
++      dlci = __get_dlci(msc->dlci);
+       BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
+       d = rfcomm_dlc_get(s, dlci);
+@@ -1640,17 +1669,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
+ {
+-      struct rfcomm_mcc *mcc = (void *) skb->data;
++      struct rfcomm_mcc *mcc;
+       u8 type, cr, len;
++      mcc = skb_pull_data(skb, sizeof(*mcc));
++      if (!mcc)
++              return -EILSEQ;
++
+       cr   = __test_cr(mcc->type);
+       type = __get_mcc_type(mcc->type);
+       len  = __get_mcc_len(mcc->len);
+       BT_DBG("%p type 0x%x cr %d", s, type, cr);
+-      skb_pull(skb, 2);
+-
+       switch (type) {
+       case RFCOMM_PN:
+               rfcomm_recv_pn(s, cr, skb);
+-- 
+2.53.0
+
diff --git a/queue-6.1/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-6.1/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..98a96a9
--- /dev/null
@@ -0,0 +1,71 @@
+From 7a9bdea4f68036b07711fe38500ffa0558e0a401 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index d4c2bc5c0ef457..38fe5c31699bc1 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1588,18 +1588,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-6.1/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-6.1/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..4c1c5e8
--- /dev/null
@@ -0,0 +1,53 @@
+From 7ee2facfa61ce6a095f53a1d200e810c6076b509 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index 47852b9dd5eaa2..d2a89a99bd71cf 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -166,6 +166,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-6.1/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-6.1/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..0d5cc44
--- /dev/null
@@ -0,0 +1,56 @@
+From 52f2d7471dd69649f4b73ce420fa7190b1950837 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-6.1/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-6.1/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..3494947
--- /dev/null
@@ -0,0 +1,54 @@
+From b4dae8aac370b138fbf528c9d9ce9b0232bb7570 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index d898e1523a453e..7a60bbf4bee3aa 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -530,6 +530,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.1/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch b/queue-6.1/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
new file mode 100644 (file)
index 0000000..5a809fd
--- /dev/null
@@ -0,0 +1,107 @@
+From 069404dfdfb6001db5fc68846b408ca92c65ec83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 13:18:11 +0300
+Subject: ipv6: mcast: Fix use-after-free when processing MLD queries
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ]
+
+When processing an MLD query, a pointer to the multicast group address
+is retrieved when initially parsing the packet. This pointer is later
+dereferenced without being reloaded despite the fact that the skb header
+might have been reallocated following the pskb_may_pull() calls, leading
+to a use-after-free [1].
+
+Fix by copying the multicast group address when the packet is initially
+parsed.
+
+[1]
+BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512)
+Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
+
+Workqueue: mld mld_query_work
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+print_address_description.constprop.0 (mm/kasan/report.c:378)
+print_report (mm/kasan/report.c:482)
+kasan_report (mm/kasan/report.c:595)
+__mld_query_work (net/ipv6/mcast.c:1512)
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+</TASK>
+
+[...]
+
+Freed by task 118:
+kasan_save_stack (mm/kasan/common.c:57)
+kasan_save_track (mm/kasan/common.c:78)
+kasan_save_free_info (mm/kasan/generic.c:584)
+__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
+kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566)
+pskb_expand_head (net/core/skbuff.c:2335)
+__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4))
+__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+
+Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Reviewed-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/mcast.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index e7f569875e7186..f6af19b873a41d 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1392,9 +1392,9 @@ void igmp6_event_query(struct sk_buff *skb)
+ static void __mld_query_work(struct sk_buff *skb)
+ {
+       struct mld2_query *mlh2 = NULL;
+-      const struct in6_addr *group;
+       unsigned long max_delay;
+       struct inet6_dev *idev;
++      struct in6_addr group;
+       struct ifmcaddr6 *ma;
+       struct mld_msg *mld;
+       int group_type;
+@@ -1426,8 +1426,8 @@ static void __mld_query_work(struct sk_buff *skb)
+               goto kfree_skb;
+       mld = (struct mld_msg *)icmp6_hdr(skb);
+-      group = &mld->mld_mca;
+-      group_type = ipv6_addr_type(group);
++      group = mld->mld_mca;
++      group_type = ipv6_addr_type(&group);
+       if (group_type != IPV6_ADDR_ANY &&
+           !(group_type&IPV6_ADDR_MULTICAST))
+@@ -1477,7 +1477,7 @@ static void __mld_query_work(struct sk_buff *skb)
+               }
+       } else {
+               for_each_mc_mclock(idev, ma) {
+-                      if (!ipv6_addr_equal(group, &ma->mca_addr))
++                      if (!ipv6_addr_equal(&group, &ma->mca_addr))
+                               continue;
+                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                               /* gsquery <- gsquery && mark */
+-- 
+2.53.0
+
diff --git a/queue-6.1/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-6.1/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..2eb1641
--- /dev/null
@@ -0,0 +1,127 @@
+From 47752dc8d230f26d6eb3c74c0a6b76d53b3c9348 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index abc46f05762e6b..0b175ecd9562bd 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1407,8 +1407,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 6cc50f05c46c15..15a083dd459737 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1415,7 +1415,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1477,9 +1477,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1487,6 +1486,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1543,7 +1546,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index d4903723be7e90..49b2e5d2b2c837 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-6.1/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..8567edf
--- /dev/null
@@ -0,0 +1,79 @@
+From 8d42bd4c2339914c5d72af008537d8e761307c60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index 6c927d4b35f06e..dea0fd28cbed88 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -702,6 +702,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -752,6 +758,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-annotate-sk-sk_write_space-for-udp-sockmap.patch b/queue-6.1/net-annotate-sk-sk_write_space-for-udp-sockmap.patch
new file mode 100644 (file)
index 0000000..8d6ba47
--- /dev/null
@@ -0,0 +1,60 @@
+From 96e4e4d4a0a9d81b49be0034bcad03d7e64d97da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:39:23 +0000
+Subject: net: Annotate sk->sk_write_space() for UDP SOCKMAP.
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit b748765019fe9e9234660327090fc1a9665cdbdd ]
+
+UDP TX skb->destructor() is sock_wfree(), and UDP holds lock_sock()
+only for UDP_CORK / MSG_MORE sendmsg().
+
+Otherwise, sk->sk_write_space() may be read locklessly while SOCKMAP
+rewrites sk->sk_write_space().
+
+Let's use WRITE_ONCE() and READ_ONCE() for sk->sk_write_space().
+
+Note that the write side is annotated by commit 2ef2b20cf4e0
+("net: annotate data-races around sk->sk_{data_ready,write_space}").
+
+Fixes: 7b98cd42b049 ("bpf: sockmap: Add UDP support")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://patch.msgid.link/20260529193941.3897256-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 6c178b47426669..62411c8870e855 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2433,8 +2433,12 @@ void sock_wfree(struct sk_buff *skb)
+       bool free;
+       if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
++              void (*sk_write_space)(struct sock *sk);
++
++              sk_write_space = READ_ONCE(sk->sk_write_space);
++
+               if (sock_flag(sk, SOCK_RCU_FREE) &&
+-                  sk->sk_write_space == sock_def_write_space) {
++                  sk_write_space == sock_def_write_space) {
+                       rcu_read_lock();
+                       free = refcount_sub_and_test(len, &sk->sk_wmem_alloc);
+                       sock_def_write_space_wfree(sk);
+@@ -2449,7 +2453,7 @@ void sock_wfree(struct sk_buff *skb)
+                * after sk_write_space() call
+                */
+               WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
+-              sk->sk_write_space(sk);
++              sk_write_space(sk);
+               len = 1;
+       }
+       /*
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch b/queue-6.1/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
new file mode 100644 (file)
index 0000000..e091894
--- /dev/null
@@ -0,0 +1,62 @@
+From 1e5682714e8ed1da386872b3f5443f0fc6a1e352 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 06:18:57 +0000
+Subject: net: fec: fix pinctrl default state restore order on resume
+
+From: Tapio Reijonen <tapio.reijonen@vaisala.com>
+
+[ Upstream commit b455410146bf723c7ebcb49ecd5becc0d6611482 ]
+
+In fec_resume(), fec_enet_clk_enable() is called before
+pinctrl_pm_select_default_state() in the non-WoL path, inverting the
+ordering used in fec_suspend() which correctly switches to the sleep
+pinctrl state before disabling clocks.
+
+For PHYs with the PHY_RST_AFTER_CLK_EN flag (e.g. TI DP83848 or
+SMSC LAN87xx), fec_enet_clk_enable() triggers a hardware reset pulse
+via the phy-reset GPIO. With the GPIO pin still in sleep pinctrl state
+at that point, the GPIO write has no physical effect and the PHY never
+receives the required reset after clock enable, leading to unreliable
+link establishment after system resume.
+
+Fix by restoring the default pinctrl state before enabling clocks,
+making resume the proper mirror of suspend. The call is made
+unconditionally: fec_suspend() only switches to the sleep pinctrl state
+on the non-WoL path and leaves the pins in the default state when WoL
+is enabled, so on a WoL resume the device is already in the default
+state and pinctrl_pm_select_default_state() is a no-op.
+
+Fixes: de40ed31b3c5 ("net: fec: add Wake-on-LAN support")
+Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20260529-b4-fec-resume-pinctrl-order-v3-1-6eda0f592fca@vaisala.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index e9c4945d0c2713..d1510af6aff1b5 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -4322,6 +4322,7 @@ static int __maybe_unused fec_resume(struct device *dev)
+               if (fep->rpm_active)
+                       pm_runtime_force_resume(dev);
++              pinctrl_pm_select_default_state(&fep->pdev->dev);
+               ret = fec_enet_clk_enable(ndev, true);
+               if (ret) {
+                       rtnl_unlock();
+@@ -4338,8 +4339,6 @@ static int __maybe_unused fec_resume(struct device *dev)
+                       val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
+                       writel(val, fep->hwp + FEC_ECNTRL);
+                       fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
+-              } else {
+-                      pinctrl_pm_select_default_state(&fep->pdev->dev);
+               }
+               fec_restart(ndev);
+               netif_tx_lock_bh(ndev);
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-6.1/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..dc10d80
--- /dev/null
@@ -0,0 +1,58 @@
+From 6e40d171b9819dfe5707ea7a2796a4daf92d62f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index fc9eb02a912f81..f8037227e6dd66 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -452,7 +452,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-6.1/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..651a32e
--- /dev/null
@@ -0,0 +1,99 @@
+From 7df39d54a71914f8a75f58e323e56e6244f1ddab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 5dacc786db4559..c51d316ccdfb86 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -1271,6 +1271,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -1310,6 +1340,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       eth_hw_addr_set(netdev, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index c0d209f36188a1..9f20c727a7e137 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -180,6 +180,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-6.1/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-6.1/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..215ef60
--- /dev/null
@@ -0,0 +1,106 @@
+From 82e15b7f2b587e340d1f585eec4be0c2bedb03a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index 31e8d8f8bcd7eb..55e3b5ec1d92d8 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -42,6 +42,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *act_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index b75e22756c4b09..47f0d4c3dc487f 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -111,11 +111,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -128,7 +123,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void offload_action_hw_count_set(struct tc_action *act,
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-6.1/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..d9360c3
--- /dev/null
@@ -0,0 +1,58 @@
+From 6f049ce4657e6963d0b7c56e3d0dc94a81048981 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-6.1/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..5d997e8
--- /dev/null
@@ -0,0 +1,50 @@
+From 549a8637c5f59dcc9e05d3a02424b4db609f4366 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index 5703846bea3b69..0f50ea92ced9df 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -208,7 +208,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -222,7 +222,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-6.1/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..9e0b0ee
--- /dev/null
@@ -0,0 +1,113 @@
+From d5810721e683d187a1cb80440aefae3c859ed075 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index f5a52075691faa..500a90311ed505 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -21,6 +21,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -768,26 +770,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1192,27 +1199,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-6.1/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-6.1/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..d79f1ec
--- /dev/null
@@ -0,0 +1,41 @@
+From 13fa5a1978240b227253246af2e2a816ef9b2314 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-6.1/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch b/queue-6.1/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
new file mode 100644 (file)
index 0000000..c011517
--- /dev/null
@@ -0,0 +1,119 @@
+From 008a9b234b914d27cac828a11788de0d1b71504f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 10:28:53 +0530
+Subject: octeontx2-af: npc: Fix CPT channel mask in npc_install_flow
+
+From: Nithin Dabilpuram <ndabilpuram@marvell.com>
+
+[ Upstream commit 1d31eb27e570daa04f5373345f9ac98c95863be9 ]
+
+Use the CPT-aware NIX channel mask in the npc_install_flow path so that
+when the host PF installs steering rules in kernel for a VF used from
+userspace (e.g. DPDK), MCAM entries see the same channel mask semantics as
+other RX paths.
+
+Fixes: 56bcef528bd8 ("octeontx2-af: Use npc_install_flow API for promisc and broadcast entries")
+Cc: Naveen Mamindlapalli <naveenm@marvell.com>
+Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
+Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
+Link: https://patch.msgid.link/20260602045853.1558530-1-rkannoth@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |  1 +
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   | 32 +++++++++----------
+ .../marvell/octeontx2/af/rvu_npc_fs.c         |  2 +-
+ 3 files changed, 18 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index fc0f3398a556bb..86ef67745ebdf7 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -895,6 +895,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
+                       int slot);
+ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);
+ int rvu_cpt_init(struct rvu *rvu);
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu);
+ #define NDC_AF_BANK_MASK       GENMASK_ULL(7, 0)
+ #define NDC_AF_BANK_LINE_MASK  GENMASK_ULL(31, 16)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 9b8a6046e6dff0..65ad7476e60983 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -609,6 +609,19 @@ static u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
+                         NPC_AF_MCAMEX_BANKX_ACTION(index, bank));
+ }
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu)
++{
++      /* For cn10k the upper two bits of the channel number are
++       * cpt channel number. with masking out these bits in the
++       * mcam entry, same entry used for NIX will allow packets
++       * received from cpt for parsing.
++       */
++      if (!is_rvu_otx2(rvu))
++              return NIX_CHAN_CPT_X2P_MASK;
++      else
++              return 0xFFFu;
++}
++
+ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+                                int nixlf, u64 chan, u8 *mac_addr)
+ {
+@@ -652,7 +665,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+       eth_broadcast_addr((u8 *)&req.mask.dmac);
+       req.features = BIT_ULL(NPC_DMAC);
+       req.channel = chan;
+-      req.chan_mask = 0xFFFU;
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.intf = pfvf->nix_rx_intf;
+       req.op = action.op;
+       req.hdr.pcifunc = 0; /* AF is requester */
+@@ -722,11 +735,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+        * mcam entry, same entry used for NIX will allow packets
+        * received from cpt for parsing.
+        */
+-      if (!is_rvu_otx2(rvu)) {
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      } else {
+-              req.chan_mask = 0xFFFU;
+-      }
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       if (chan_cnt > 1) {
+               if (!is_power_of_2(chan_cnt)) {
+@@ -915,16 +924,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+       ether_addr_copy(req.mask.dmac, mac_addr);
+       req.features = BIT_ULL(NPC_DMAC);
+-      /* For cn10k the upper two bits of the channel number are
+-       * cpt channel number. with masking out these bits in the
+-       * mcam entry, same entry used for NIX will allow packets
+-       * received from cpt for parsing.
+-       */
+-      if (!is_rvu_otx2(rvu))
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      else
+-              req.chan_mask = 0xFFFU;
+-
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.channel = chan;
+       req.intf = pfvf->nix_rx_intf;
+       req.entry = index;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+index 80d6aa3f14c11f..b79b28192a5764 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+@@ -1320,7 +1320,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
+       /* ignore chan_mask in case pf func is not AF, revisit later */
+       if (!is_pffunc_af(req->hdr.pcifunc))
+-              req->chan_mask = 0xFFF;
++              req->chan_mask = rvu_get_cpt_chan_mask(rvu);
+       err = npc_check_unsupported_flows(rvu, req->features, req->intf);
+       if (err)
+-- 
+2.53.0
+
diff --git a/queue-6.1/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-6.1/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..e4b83cb
--- /dev/null
@@ -0,0 +1,58 @@
+From 16ef2f9bf8b59d0e5f2d29e7d3374374dad2677f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 72db9f9e7beeae..81cb83caf62a15 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1403,8 +1403,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1412,9 +1414,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/ptp-vclock-switch-from-rcu-to-srcu.patch b/queue-6.1/ptp-vclock-switch-from-rcu-to-srcu.patch
new file mode 100644 (file)
index 0000000..b1b3874
--- /dev/null
@@ -0,0 +1,85 @@
+From 7b283be128c82c8d41ab77f641af44db44e15d43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:11:47 +0200
+Subject: ptp: vclock: Switch from RCU to SRCU
+
+From: Kurt Kanzenbach <kurt@linutronix.de>
+
+[ Upstream commit 672bd0519e27c357c43b7f8c0d653fce3817d06e ]
+
+The usage of PTP vClocks leads immediately to the following issues with
+ptp4l with LOCKDEP and DEBUG_ATOMIC_SLEEP enabled: "BUG: sleeping function
+called from invalid context".
+
+ptp_convert_timestamp() acquires a mutex_t within a RCU read section.  This
+is illegal, because acquiring a mutex_t can result in voluntary scheduling
+request which is not allowed within a RCU read section.
+
+Replace the RCU usage with SRCU where sleeping is allowed.
+
+Reported-by: Florian Zeitz <florian.zeitz@schettke.com>
+Closes: https://lore.kernel.org/all/00a8cce8-410e-4038-98af-49be6d93d7bd@schettke.com/
+Fixes: 67d93ffc0f3c ("ptp: vclock: use mutex to fix "sleep on atomic" bug")
+Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260529-vclock_rcu-v2-1-02a5531fab92@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_vclock.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
+index dcf752c9e04506..eb57338a32414a 100644
+--- a/drivers/ptp/ptp_vclock.c
++++ b/drivers/ptp/ptp_vclock.c
+@@ -19,6 +19,8 @@ static DEFINE_SPINLOCK(vclock_hash_lock);
+ static DEFINE_READ_MOSTLY_HASHTABLE(vclock_hash, 8);
++DEFINE_STATIC_SRCU(vclock_srcu);
++
+ static void ptp_vclock_hash_add(struct ptp_vclock *vclock)
+ {
+       spin_lock(&vclock_hash_lock);
+@@ -37,7 +39,7 @@ static void ptp_vclock_hash_del(struct ptp_vclock *vclock)
+       spin_unlock(&vclock_hash_lock);
+-      synchronize_rcu();
++      synchronize_srcu(&vclock_srcu);
+ }
+ static int ptp_vclock_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+@@ -269,14 +271,16 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+ {
+       unsigned int hash = vclock_index % HASH_SIZE(vclock_hash);
+       struct ptp_vclock *vclock;
+-      u64 ns;
+       u64 vclock_ns = 0;
++      int srcu_idx;
++      u64 ns;
+       ns = ktime_to_ns(*hwtstamp);
+-      rcu_read_lock();
++      srcu_idx = srcu_read_lock(&vclock_srcu);
+-      hlist_for_each_entry_rcu(vclock, &vclock_hash[hash], vclock_hash_node) {
++      hlist_for_each_entry_srcu(vclock, &vclock_hash[hash], vclock_hash_node,
++                                srcu_read_lock_held(&vclock_srcu)) {
+               if (vclock->clock->index != vclock_index)
+                       continue;
+@@ -287,7 +291,7 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+               break;
+       }
+-      rcu_read_unlock();
++      srcu_read_unlock(&vclock_srcu, srcu_idx);
+       return ns_to_ktime(vclock_ns);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-6.1/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..34dff62
--- /dev/null
@@ -0,0 +1,87 @@
+From 0b159fc6cf012d4af0609f7fecac6c45ab09b7a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 1685f73602d5e3..f5dc7822d220f2 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2599,11 +2599,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
index b52eb86872257a27935ee1b00a57bf65456f547b..705032ff5d8cba380fbe8e16f87cddac40655317 100644 (file)
@@ -191,3 +191,34 @@ bpf-free-reuseport-cbpf-prog-after-rcu-grace-period.patch
 usb-serial-mct_u232-fix-memory-corruption-with-small.patch
 dmaengine-idxd-fix-not-releasing-workqueue-on-.relea.patch
 disable-wattribute-alias-for-clang-23-and-newer.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-annotate-sk-sk_write_space-for-udp-sockmap.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
+bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
+bluetooth-bnep-reject-short-frames-before-parsing.patch
+bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
+bluetooth-mgmt-fix-backward-compatibility-with-users.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ptp-vclock-switch-from-rcu-to-srcu.patch
+octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
+vxlan-vnifilter-send-notification-on-vni-add.patch
+vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
+ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
diff --git a/queue-6.1/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-6.1/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..0d063a3
--- /dev/null
@@ -0,0 +1,287 @@
+From a7533b9bc4c9575e33c510069be43f4ba018d49c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index d0f397c9024201..2386bbd38ce78b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch b/queue-6.1/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
new file mode 100644 (file)
index 0000000..e594ecb
--- /dev/null
@@ -0,0 +1,55 @@
+From 0a6687f0501158dd054feafaf4dd4d8a6da012f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:37 -0700
+Subject: vxlan: vnifilter: fix spurious notification on VNI update
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit 84683b5b60c7274e2c8f7f413d39d78d3db5540f ]
+
+When a VNI is re-added with the same attributes (e.g. same group or no
+group), vxlan_vni_update() sends a spurious RTM_NEWTUNNEL notification
+even though nothing changed.
+
+The bug is that 'if (changed)' tests whether the pointer is non-NULL,
+not the bool value it points to. Since every caller passes a valid
+pointer, the condition is always true and the notification fires
+unconditionally.
+
+Fix by dereferencing the pointer: 'if (*changed)'.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100
+ # bridge vni add vni 1000 dev vxlan100  # spurious notification
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-3-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index ca866740a955d0..abf96d60eb30d5 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -671,7 +671,7 @@ static int vxlan_vni_update(struct vxlan_dev *vxlan,
+       if (ret)
+               return ret;
+-      if (changed)
++      if (*changed)
+               vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.1/vxlan-vnifilter-send-notification-on-vni-add.patch b/queue-6.1/vxlan-vnifilter-send-notification-on-vni-add.patch
new file mode 100644 (file)
index 0000000..8c1b434
--- /dev/null
@@ -0,0 +1,69 @@
+From bd89c4769ddff8e567d5b52a1fb30dee09ee7886 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:36 -0700
+Subject: vxlan: vnifilter: send notification on VNI add
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit aa6ca1c5c338907817374b59f7551fd855a88754 ]
+
+When a new VNI is added to a vxlan device with vnifilter enabled,
+no RTM_NEWTUNNEL notification is sent to userspace. This means
+'bridge monitor vni' never shows VNI add events, even though
+VNI delete events are reported correctly.
+
+The bug is in vxlan_vni_add(), where the notification is guarded by
+'if (changed)'. The 'changed' flag is set by vxlan_vni_update_group()
+only when the multicast group or remote IP is modified, but for a
+new VNI added without a group (e.g. in L3 VxLAN interface scenarios),
+the function returns early without setting changed=true. Since this
+is a new VNI, the notification should be sent unconditionally.
+
+The notification is not guarded by the return value of
+vxlan_vni_update_group() because, at this point, the VNI has already
+been inserted into the hash table and list with no rollback on error.
+The VNI will be visible in 'bridge vni show' regardless, so userspace
+should be informed. This is consistent with vxlan_vni_del() which also
+notifies unconditionally.
+
+The 'if (changed)' guard remains correct in vxlan_vni_update(), which
+handles the case where a VNI already exists and is being re-added --
+there, we only want to notify if the group/remote actually changed.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100    # no notification
+ # bridge vni delete vni 1000 dev vxlan100 # notification received
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Reported-by: Chirag Shah <chirag@nvidia.com>
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-2-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index c6d4fae958ca80..ca866740a955d0 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -769,8 +769,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+       err = vxlan_vni_update_group(vxlan, vninode, group, true, &changed,
+                                    extack);
+-      if (changed)
+-              vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
++      vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return err;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-6.12/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..b0c625e
--- /dev/null
@@ -0,0 +1,67 @@
+From 1c4e9569df149491ee33428b3b1105826887a71a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index e116d308a8df6d..37eaff3f7b6940 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch b/queue-6.12/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
new file mode 100644 (file)
index 0000000..3896971
--- /dev/null
@@ -0,0 +1,71 @@
+From 15bcba5ce3ba4bb008cb056fbbc271df62669764 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 17:39:53 +0800
+Subject: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame()
+ extension handling
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+[ Upstream commit 72b8deccff17a7644e0367e1aaf1a36cfb014324 ]
+
+In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
+BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:
+
+1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
+   performs a native-endian read. The BNEP protocol specifies this field
+   in big-endian (network byte order), and the same file correctly uses
+   get_unaligned_be16() for the identical fields in
+   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().
+
+2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
+   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
+   entry), the filter extension length field already represents the total
+   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
+   which reads the same field as a byte count and divides by 4 to get
+   the number of filter entries.
+
+   The bogus * 2 means skb_pull advances twice as far as it should,
+   either dropping valid data from the next header or causing the pull
+   to fail entirely when the doubled length exceeds the remaining skb.
+
+Fix by splitting the pull into two steps: first use skb_pull_data() to
+safely pull and validate the 3-byte fixed header (ctrl type + length),
+then pull the variable-length data using the properly decoded length.
+
+Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index b3cef7a4db5412..0de5df690bd0b2 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+                               goto badframe;
+                       break;
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET:
+-                      /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+-                      if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
++              case BNEP_FILTER_NET_TYPE_SET: {
++                      u8 *hdr;
++
++                      /* Pull ctrl type (1 b) + len (2 b) */
++                      hdr = skb_pull_data(skb, 3);
++                      if (!hdr)
++                              goto badframe;
++                      /* Pull data (len bytes); length is big-endian */
++                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+                               goto badframe;
+                       break;
++              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-bnep-reject-short-frames-before-parsing.patch b/queue-6.12/bluetooth-bnep-reject-short-frames-before-parsing.patch
new file mode 100644 (file)
index 0000000..aa44bc7
--- /dev/null
@@ -0,0 +1,170 @@
+From 961c818b74013a279fe4f5335d89ce589e52f32e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 11:22:09 +0800
+Subject: Bluetooth: bnep: reject short frames before parsing
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 6770d3a8acdf9151769180cc3710346c4cfbe6f0 ]
+
+A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
+packet type byte immediately and, for control packets, reads the control
+opcode and setup UUID-size byte before proving that those bytes are
+present. bnep_rx_control() also dereferences the control opcode without
+rejecting an empty control payload.
+
+Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
+return gates each dereference. Split the control handler so the frame
+path can pass an opcode that has already been pulled, and keep the
+byte-buffer wrapper for extension control payloads.
+
+For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
+setup payload. struct bnep_setup_conn_req carries destination and source
+service UUIDs after that byte, each uuid_size bytes, so the parser now
+documents that tuple explicitly instead of leaving the pull length as an
+opaque multiplication.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
+The buggy address belongs to the object at ffff88800c0f7908 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 1-byte
+region [ffff88800c0f7908, ffff88800c0f7909)
+Read of size 1
+Call trace:
+  dump_stack_lvl+0xb3/0x140 (?:?)
+  print_address_description+0x57/0x3a0 (?:?)
+  bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
+  print_report+0xb9/0x2b0 (?:?)
+  __virt_addr_valid+0x1ba/0x3a0 (?:?)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  kasan_addr_to_slab+0x21/0x60 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
+  worker_thread+0x65c/0xe40 (?:?)
+  __kthread_parkme+0x184/0x230 (?:?)
+  kthread+0x35e/0x470 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  ret_from_fork+0x586/0x870 (?:?)
+  __switch_to+0x74f/0xdc0 (?:?)
+  ret_from_fork_asm+0x1a/0x30 (?:?)
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index 0de5df690bd0b2..5c5f53ff30e8e5 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
+       return 0;
+ }
+-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
++                             int len)
+ {
+-      u8  cmd = *(u8 *)data;
+       int err = 0;
+-      data++;
+-      len--;
+-
+       switch (cmd) {
+       case BNEP_CMD_NOT_UNDERSTOOD:
+       case BNEP_SETUP_CONN_RSP:
+@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+       return err;
+ }
++static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++{
++      if (len < 1)
++              return -EILSEQ;
++
++      return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
++}
++
+ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct bnep_ext_hdr *h;
+@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct net_device *dev = s->dev;
+       struct sk_buff *nskb;
++      u8 *data;
+       u8 type, ctrl_type;
+       dev->stats.rx_bytes += skb->len;
+-      type = *(u8 *) skb->data;
+-      skb_pull(skb, 1);
+-      ctrl_type = *(u8 *)skb->data;
++      data = skb_pull_data(skb, sizeof(type));
++      if (!data)
++              goto badframe;
++      type = *data;
+       if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
+               goto badframe;
+       if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
+-              if (bnep_rx_control(s, skb->data, skb->len) < 0) {
++              data = skb_pull_data(skb, sizeof(ctrl_type));
++              if (!data)
++                      goto badframe;
++              ctrl_type = *data;
++
++              if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
+                       dev->stats.tx_errors++;
+                       kfree_skb(skb);
+                       return 0;
+@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+               /* Verify and pull ctrl message since it's already processed */
+               switch (ctrl_type) {
+-              case BNEP_SETUP_CONN_REQ:
+-                      /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+-                      if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
++              case BNEP_SETUP_CONN_REQ: {
++                      u8 uuid_size;
++
++                      /* Pull uuid_size and the dst/src service UUIDs. */
++                      data = skb_pull_data(skb, sizeof(uuid_size));
++                      if (!data)
++                              goto badframe;
++                      uuid_size = *data;
++                      if (!skb_pull(skb, uuid_size + uuid_size))
+                               goto badframe;
+                       break;
++              }
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET: {
+-                      u8 *hdr;
+-
+-                      /* Pull ctrl type (1 b) + len (2 b) */
+-                      hdr = skb_pull_data(skb, 3);
+-                      if (!hdr)
++              case BNEP_FILTER_NET_TYPE_SET:
++                      /* Pull: len (2 b), data (len bytes) */
++                      data = skb_pull_data(skb, sizeof(u16));
++                      if (!data)
+                               goto badframe;
+-                      /* Pull data (len bytes); length is big-endian */
+-                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
++                      if (!skb_pull(skb, get_unaligned_be16(data)))
+                               goto badframe;
+                       break;
+-              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch b/queue-6.12/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
new file mode 100644 (file)
index 0000000..d678121
--- /dev/null
@@ -0,0 +1,58 @@
+From 34e0ccb47e3cdcf4b39ba32abfc0d8d5e5869d4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 08:54:26 +0530
+Subject: Bluetooth: fix memory leak in error path of hci_alloc_dev()
+
+From: Bharath Reddy <kbreddy.rpbc@gmail.com>
+
+[ Upstream commit 37b3009bf5976e8ab77c8b9a9bc3bbd7ff49e37f ]
+
+Early failures in Bluetooth HCI UART configuration leak SRCU percpu
+memory.
+
+When device initialization fails before hci_register_dev() completes,
+the HCI_UNREGISTER flag is never set. As a result, when the device
+reference count reaches zero, bt_host_release() evaluates this flag as
+false and falls back to a direct kfree(hdev).
+
+Because hci_release_dev() is bypassed, the SRCU struct initialized
+early in hci_alloc_dev() is never cleaned up, resulting in a leak of
+percpu memory.
+
+Fix the leak by explicitly calling cleanup_srcu_struct() in the
+fallback (unregistered) branch of bt_host_release() before freeing
+the device.
+
+Reported-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=535ecc844591e50588a5
+Tested-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Fixes: 1d6123102e9f ("Bluetooth: hci_core: Fix use-after-free in vhci_flush()")
+Signed-off-by: Bharath Reddy <kbreddy.rpbc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sysfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
+index 4b54dbbf0729a3..60350c6723cb76 100644
+--- a/net/bluetooth/hci_sysfs.c
++++ b/net/bluetooth/hci_sysfs.c
+@@ -83,10 +83,12 @@ static void bt_host_release(struct device *dev)
+ {
+       struct hci_dev *hdev = to_hci_dev(dev);
+-      if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
++      if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_release_dev(hdev);
+-      else
++      } else {
++              cleanup_srcu_struct(&hdev->srcu);
+               kfree(hdev);
++      }
+       module_put(THIS_MODULE);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch b/queue-6.12/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch
new file mode 100644 (file)
index 0000000..ad30114
--- /dev/null
@@ -0,0 +1,157 @@
+From 4999de8721dfb9b1e89baa6c551bd6a7570c8633 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 20:19:07 +0900
+Subject: Bluetooth: ISO: Fix data-race on iso_pi fields in hci_get_route calls
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 9ca7053d6215d89c33f28893bfd1625a32919d3f ]
+
+iso_connect_bis(), iso_connect_cis(), iso_listen_bis(), and
+iso_conn_big_sync() call hci_get_route() using iso_pi(sk)->dst,
+iso_pi(sk)->src, and iso_pi(sk)->src_type without holding lock_sock().
+
+These fields may be modified concurrently by connect() or setsockopt()
+on the same socket, resulting in data-races reported by KCSAN.
+
+Fix this by snapshotting the required fields under lock_sock() before
+calling hci_get_route().
+
+BUG: KCSAN: data-race in memcmp+0x45/0xb0
+
+race at unknown origin, with read to 0xffff8880122135cf of 1 bytes
+by task 333 on cpu 1:
+ memcmp+0x45/0xb0
+ hci_get_route+0x27e/0x490
+ iso_connect_cis+0x4c/0xa10
+ iso_sock_connect+0x60e/0xb30
+ __sys_connect_file+0xbd/0xe0
+ __sys_connect+0xe0/0x110
+ __x64_sys_connect+0x40/0x50
+ x64_sys_call+0xcad/0x1c60
+ do_syscall_64+0x133/0x590
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 241f51931c35 ("Bluetooth: ISO: Avoid circular locking dependency")
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 60 +++++++++++++++++++++++++++++++++------------
+ 1 file changed, 44 insertions(+), 16 deletions(-)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index f9aa59c7ac0080..c0530442a94b9d 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -336,12 +336,20 @@ static int iso_connect_bis(struct sock *sk)
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      u8 src_type, bc_sid;
+       int err;
+-      BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      bc_sid = iso_pi(sk)->bc_sid;
++      release_sock(sk);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      BT_DBG("%pMR (SID 0x%2.2x)", &src, bc_sid);
++
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -431,12 +439,19 @@ static int iso_connect_cis(struct sock *sk)
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      u8 src_type;
+       int err;
+-      BT_DBG("%pMR -> %pMR", &iso_pi(sk)->src, &iso_pi(sk)->dst);
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      release_sock(sk);
++
++      BT_DBG("%pMR -> %pMR", &src, &dst);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -1123,18 +1138,25 @@ static int iso_sock_connect(struct socket *sock, struct sockaddr *addr,
+ static int iso_listen_bis(struct sock *sk)
+ {
+-      struct hci_dev *hdev;
+-      int err = 0;
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
++      struct hci_dev *hdev;
++      bdaddr_t src, dst;
++      u8 src_type, bc_sid;
++      int err = 0;
++
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      bc_sid = iso_pi(sk)->bc_sid;
++      release_sock(sk);
+-      BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
+-             &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
++      BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &src, &dst, bc_sid);
+       write_lock(&iso_sk_list.lock);
+-      if (__iso_get_sock_listen_by_sid(&iso_pi(sk)->src, &iso_pi(sk)->dst,
+-                                       iso_pi(sk)->bc_sid))
++      if (__iso_get_sock_listen_by_sid(&src, &dst, bc_sid))
+               err = -EADDRINUSE;
+       write_unlock(&iso_sk_list.lock);
+@@ -1142,8 +1164,7 @@ static int iso_listen_bis(struct sock *sk)
+       if (err)
+               return err;
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -1422,9 +1443,16 @@ static void iso_conn_big_sync(struct sock *sk)
+ {
+       int err;
+       struct hci_dev *hdev;
++      bdaddr_t src, dst;
++      u8 src_type;
++
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      release_sock(sk);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return;
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch b/queue-6.12/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch
new file mode 100644 (file)
index 0000000..7254181
--- /dev/null
@@ -0,0 +1,36 @@
+From 37a890e21fa6e9bce10ce02177f7a4360d8555e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 14:45:42 -0400
+Subject: Bluetooth: ISO: Fix not releasing hdev reference on iso_conn_big_sync
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 5cbf290b79351971f20c7a533247e8d58a3f970c ]
+
+hci_get_route() returns a reference-counted hci_dev pointer via
+hci_dev_hold(). The function exits normally or with an error without ever
+releasing it.
+
+Fixes: 07a9342b94a9 ("Bluetooth: ISO: Send BIG Create Sync via hci_sync")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index f262c32da4f29b..935e230484b78c 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1445,6 +1445,7 @@ static void iso_conn_big_sync(struct sock *sk)
+       release_sock(sk);
+       hci_dev_unlock(hdev);
++      hci_dev_put(hdev);
+ }
+ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-iso-fix-not-using-bc_sid-as-advertisement-.patch b/queue-6.12/bluetooth-iso-fix-not-using-bc_sid-as-advertisement-.patch
new file mode 100644 (file)
index 0000000..40abe58
--- /dev/null
@@ -0,0 +1,333 @@
+From 29432e730d9bed25fd426c6d7c32fe4c635e41f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jun 2025 14:32:49 -0400
+Subject: Bluetooth: ISO: Fix not using bc_sid as advertisement SID
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 5842c01a9ed1d515c8ba2d6d3733eac78ace89c1 ]
+
+Currently bc_sid is being ignore when acting as Broadcast Source role,
+so this fix it by passing the bc_sid and then use it when programming
+the PA:
+
+< HCI Command: LE Set Exte.. (0x08|0x0036) plen 25
+        Handle: 0x01
+        Properties: 0x0000
+        Min advertising interval: 140.000 msec (0x00e0)
+        Max advertising interval: 140.000 msec (0x00e0)
+        Channel map: 37, 38, 39 (0x07)
+        Own address type: Random (0x01)
+        Peer address type: Public (0x00)
+        Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
+        Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
+        TX power: Host has no preference (0x7f)
+        Primary PHY: LE 1M (0x01)
+        Secondary max skip: 0x00
+        Secondary PHY: LE 2M (0x02)
+        SID: 0x01
+        Scan request notifications: Disabled (0x00)
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 9ca7053d6215 ("Bluetooth: ISO: Fix data-race on iso_pi fields in hci_get_route calls")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci_core.h |  9 ++++++---
+ include/net/bluetooth/hci_sync.h |  4 ++--
+ net/bluetooth/hci_conn.c         | 31 ++++++++++++++++++++++++-------
+ net/bluetooth/hci_core.c         | 16 +++++++++++++++-
+ net/bluetooth/hci_sync.c         | 20 +++++++++++++++++---
+ net/bluetooth/iso.c              | 12 ++++++++----
+ 6 files changed, 72 insertions(+), 20 deletions(-)
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index ba5d176069a692..a0c84a83f25eb1 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -244,6 +244,7 @@ struct adv_info {
+       __u8    mesh;
+       __u8    instance;
+       __u8    handle;
++      __u8    sid;
+       __u32   flags;
+       __u16   timeout;
+       __u16   remaining_time;
+@@ -1576,13 +1577,14 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
+                                u16 timeout);
+ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
+                             __u8 dst_type, struct bt_iso_qos *qos);
+-struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
++struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
+                             struct bt_iso_qos *qos,
+                             __u8 base_len, __u8 *base);
+ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
+                                __u8 dst_type, struct bt_iso_qos *qos);
+ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
+-                               __u8 dst_type, struct bt_iso_qos *qos,
++                               __u8 dst_type, __u8 sid,
++                               struct bt_iso_qos *qos,
+                                __u8 data_len, __u8 *data);
+ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
+                      __u8 dst_type, __u8 sid, struct bt_iso_qos *qos);
+@@ -1846,6 +1848,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ void hci_adv_instances_clear(struct hci_dev *hdev);
+ struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance);
++struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid);
+ struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance);
+ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
+                                     u32 flags, u16 adv_data_len, u8 *adv_data,
+@@ -1853,7 +1856,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
+                                     u16 timeout, u16 duration, s8 tx_power,
+                                     u32 min_interval, u32 max_interval,
+                                     u8 mesh_handle);
+-struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
++struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid,
+                                     u32 flags, u8 data_len, u8 *data,
+                                     u32 min_interval, u32 max_interval);
+ int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance,
+diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
+index 17e5112f7840e0..4d3132a50ef058 100644
+--- a/include/net/bluetooth/hci_sync.h
++++ b/include/net/bluetooth/hci_sync.h
+@@ -115,8 +115,8 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance);
+ int hci_enable_advertising_sync(struct hci_dev *hdev);
+ int hci_enable_advertising(struct hci_dev *hdev);
+-int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
+-                         u8 *data, u32 flags, u16 min_interval,
++int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid,
++                         u8 data_len, u8 *data, u32 flags, u16 min_interval,
+                          u16 max_interval, u16 sync_interval);
+ int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance);
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index f89af453cb3b18..d34c66b92fbc1b 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1494,8 +1494,8 @@ static int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos)
+ /* This function requires the caller holds hdev->lock */
+ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
+-                                  struct bt_iso_qos *qos, __u8 base_len,
+-                                  __u8 *base)
++                                  __u8 sid, struct bt_iso_qos *qos,
++                                  __u8 base_len, __u8 *base)
+ {
+       struct hci_conn *conn;
+       int err;
+@@ -1536,6 +1536,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
+               return conn;
+       conn->state = BT_CONNECT;
++      conn->sid = sid;
+       hci_conn_hold(conn);
+       return conn;
+@@ -2063,7 +2064,8 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
+       if (qos->bcast.bis)
+               sync_interval = interval * 4;
+-      err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len,
++      err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->sid,
++                                   conn->le_per_adv_data_len,
+                                    conn->le_per_adv_data, flags, interval,
+                                    interval, sync_interval);
+       if (err)
+@@ -2148,7 +2150,7 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err)
+       hci_conn_put(conn);
+ }
+-struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
++struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
+                             struct bt_iso_qos *qos,
+                             __u8 base_len, __u8 *base)
+ {
+@@ -2170,7 +2172,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
+                                                  base, base_len);
+       /* We need hci_conn object using the BDADDR_ANY as dst */
+-      conn = hci_add_bis(hdev, dst, qos, base_len, eir);
++      conn = hci_add_bis(hdev, dst, sid, qos, base_len, eir);
+       if (IS_ERR(conn))
+               return conn;
+@@ -2221,20 +2223,35 @@ static void bis_mark_per_adv(struct hci_conn *conn, void *data)
+ }
+ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
+-                               __u8 dst_type, struct bt_iso_qos *qos,
++                               __u8 dst_type, __u8 sid,
++                               struct bt_iso_qos *qos,
+                                __u8 base_len, __u8 *base)
+ {
+       struct hci_conn *conn;
+       int err;
+       struct iso_list_data data;
+-      conn = hci_bind_bis(hdev, dst, qos, base_len, base);
++      conn = hci_bind_bis(hdev, dst, sid, qos, base_len, base);
+       if (IS_ERR(conn))
+               return conn;
+       if (conn->state == BT_CONNECTED)
+               return conn;
++      /* Check if SID needs to be allocated then search for the first
++       * available.
++       */
++      if (conn->sid == HCI_SID_INVALID) {
++              u8 sid;
++
++              for (sid = 0; sid <= 0x0f; sid++) {
++                      if (!hci_find_adv_sid(hdev, sid)) {
++                              conn->sid = sid;
++                              break;
++                      }
++              }
++      }
++
+       data.big = qos->bcast.big;
+       data.bis = qos->bcast.bis;
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 677f51edb27752..e96ccdd7ef15e7 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -1602,6 +1602,19 @@ struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance)
+       return NULL;
+ }
++/* This function requires the caller holds hdev->lock */
++struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid)
++{
++      struct adv_info *adv;
++
++      list_for_each_entry(adv, &hdev->adv_instances, list) {
++              if (adv->sid == sid)
++                      return adv;
++      }
++
++      return NULL;
++}
++
+ /* This function requires the caller holds hdev->lock */
+ struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance)
+ {
+@@ -1754,7 +1767,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
+ }
+ /* This function requires the caller holds hdev->lock */
+-struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
++struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid,
+                                     u32 flags, u8 data_len, u8 *data,
+                                     u32 min_interval, u32 max_interval)
+ {
+@@ -1766,6 +1779,7 @@ struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
+       if (IS_ERR(adv))
+               return adv;
++      adv->sid = sid;
+       adv->periodic = true;
+       adv->per_adv_data_len = data_len;
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 535fd7de9b1aec..fc9977c8c42705 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -1393,10 +1393,12 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
+               hci_cpu_to_le24(adv->min_interval, cp.min_interval);
+               hci_cpu_to_le24(adv->max_interval, cp.max_interval);
+               cp.tx_power = adv->tx_power;
++              cp.sid = adv->sid;
+       } else {
+               hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval);
+               hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval);
+               cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE;
++              cp.sid = 0x00;
+       }
+       secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK);
+@@ -1730,8 +1732,8 @@ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
+       return hci_update_adv_data_sync(hdev, adv->instance);
+ }
+-int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
+-                         u8 *data, u32 flags, u16 min_interval,
++int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid,
++                         u8 data_len, u8 *data, u32 flags, u16 min_interval,
+                          u16 max_interval, u16 sync_interval)
+ {
+       struct adv_info *adv = NULL;
+@@ -1743,6 +1745,18 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
+       if (instance) {
+               adv = hci_find_adv_instance(hdev, instance);
+               if (adv) {
++                      if (sid != HCI_SID_INVALID && adv->sid != sid) {
++                              /* If the SID don't match attempt to find by
++                               * SID.
++                               */
++                              adv = hci_find_adv_sid(hdev, sid);
++                              if (!adv) {
++                                      bt_dev_err(hdev,
++                                                 "Unable to find adv_info");
++                                      return -EINVAL;
++                              }
++                      }
++
+                       /* Turn it into periodic advertising */
+                       adv->periodic = true;
+                       adv->per_adv_data_len = data_len;
+@@ -1751,7 +1765,7 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
+                       adv->flags = flags;
+               } else if (!adv) {
+                       /* Create an instance if that could not be found */
+-                      adv = hci_add_per_instance(hdev, instance, flags,
++                      adv = hci_add_per_instance(hdev, instance, sid, flags,
+                                                  data_len, data,
+                                                  sync_interval,
+                                                  sync_interval);
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 935e230484b78c..f9aa59c7ac0080 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -338,7 +338,7 @@ static int iso_connect_bis(struct sock *sk)
+       struct hci_dev  *hdev;
+       int err;
+-      BT_DBG("%pMR", &iso_pi(sk)->src);
++      BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);
+       hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+                            iso_pi(sk)->src_type);
+@@ -367,7 +367,7 @@ static int iso_connect_bis(struct sock *sk)
+       /* Just bind if DEFER_SETUP has been set */
+       if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+-              hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst,
++              hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, iso_pi(sk)->bc_sid,
+                                   &iso_pi(sk)->qos, iso_pi(sk)->base_len,
+                                   iso_pi(sk)->base);
+               if (IS_ERR(hcon)) {
+@@ -377,12 +377,16 @@ static int iso_connect_bis(struct sock *sk)
+       } else {
+               hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst,
+                                      le_addr_type(iso_pi(sk)->dst_type),
+-                                     &iso_pi(sk)->qos, iso_pi(sk)->base_len,
+-                                     iso_pi(sk)->base);
++                                     iso_pi(sk)->bc_sid, &iso_pi(sk)->qos,
++                                     iso_pi(sk)->base_len, iso_pi(sk)->base);
+               if (IS_ERR(hcon)) {
+                       err = PTR_ERR(hcon);
+                       goto unlock;
+               }
++
++              /* Update SID if it was not set */
++              if (iso_pi(sk)->bc_sid == HCI_SID_INVALID)
++                      iso_pi(sk)->bc_sid = hcon->sid;
+       }
+       conn = iso_conn_add(hcon);
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-mgmt-fix-backward-compatibility-with-users.patch b/queue-6.12/bluetooth-mgmt-fix-backward-compatibility-with-users.patch
new file mode 100644 (file)
index 0000000..11bc7c2
--- /dev/null
@@ -0,0 +1,43 @@
+From 53b15a0dd39ec6642482ef7f26bce791fa3d0f33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:48:34 -0400
+Subject: Bluetooth: MGMT: Fix backward compatibility with userspace
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 149324fc762c2a7acef9c26790566f81f475e51f ]
+
+bluetoothd has a bug with makes it send extra bytes as part of
+MGMT_OP_ADD_EXT_ADV_DATA which are now being checked to be the
+exact the expected length, relax this so only when the expected
+length is greater than the data length to cause an error since
+that would result in accessing invalid memory, otherwise just
+ignore the extra bytes.
+
+Link: https://lore.kernel.org/linux-bluetooth/20260602204749.210857-1-luiz.dentz@gmail.com/T/#u
+Fixes: d3f7d17960ed ("Bluetooth: MGMT: validate Add Extended Advertising Data length")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 040a5595f45fee..f494eda5cc81c1 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -9197,8 +9197,9 @@ static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data,
+       BT_DBG("%s", hdev->name);
+-      expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len);
+-      if (expected_len != data_len)
++      expected_len = struct_size(cp, data, cp->adv_data_len +
++                                 cp->scan_rsp_len);
++      if (expected_len > data_len)
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
+                                      MGMT_STATUS_INVALID_PARAMS);
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-6.12/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..e99357b
--- /dev/null
@@ -0,0 +1,73 @@
+From 3f65dd5340f9dc0c938815e011e8dc6e72f501dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index a2bdf25a77aece..040a5595f45fee 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -8721,6 +8721,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -8737,12 +8743,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-6.12/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..0e312bd
--- /dev/null
@@ -0,0 +1,126 @@
+From 6a42518f30b2840b611340986a5feec20c3be95a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index 3052436e9c6de5..2286efef62f5b6 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -940,6 +950,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -953,6 +964,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -980,9 +996,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       release_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch b/queue-6.12/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
new file mode 100644 (file)
index 0000000..6197caa
--- /dev/null
@@ -0,0 +1,167 @@
+From 5235f2c59d3d29f8d7013cbe22ed55e4a3b89b1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:04:43 +0900
+Subject: Bluetooth: RFCOMM: validate skb length in MCC handlers
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 23882b828c3c8c51d0c946446a396b10abb3b16b ]
+
+The RFCOMM MCC handlers cast skb->data to protocol-specific structs
+without validating skb->len first. A malicious remote device can send
+truncated MCC frames and trigger out-of-bounds reads in these handlers.
+
+Fix this by using skb_pull_data() to validate and access the required
+data before dereferencing it.
+
+rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
+1-byte RPN requests. Handle this by validating only the DLCI byte first,
+and validating the full struct only when len > 1.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
+ 1 file changed, 49 insertions(+), 18 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
+index ad5177e3a69b77..293bf67cf10d3e 100644
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -1431,10 +1431,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
+ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_pn *pn = (void *) skb->data;
++      struct rfcomm_pn *pn;
+       struct rfcomm_dlc *d;
+-      u8 dlci = pn->dlci;
++      u8 dlci;
++
++      pn = skb_pull_data(skb, sizeof(*pn));
++      if (!pn)
++              return -EILSEQ;
++      dlci = pn->dlci;
+       BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
+       if (!dlci)
+@@ -1483,8 +1488,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
+ {
+-      struct rfcomm_rpn *rpn = (void *) skb->data;
+-      u8 dlci = __get_dlci(rpn->dlci);
++      struct rfcomm_rpn *rpn;
++      u8 dlci;
+       u8 bit_rate  = 0;
+       u8 data_bits = 0;
+@@ -1495,15 +1500,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+       u8 xoff_char = 0;
+       u16 rpn_mask = RFCOMM_RPN_PM_ALL;
+-      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+-              dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+-              rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++      if (len == 1) {
++              rpn = skb_pull_data(skb, 1);
++              if (!rpn)
++                      return -EILSEQ;
+-      if (!cr)
+-              return 0;
++              dlci = __get_dlci(rpn->dlci);
++
++              if (!cr)
++                      return 0;
+-      if (len == 1) {
+-              /* This is a request, return default (according to ETSI TS 07.10) settings */
+               bit_rate  = RFCOMM_RPN_BR_9600;
+               data_bits = RFCOMM_RPN_DATA_8;
+               stop_bits = RFCOMM_RPN_STOP_1;
+@@ -1514,6 +1520,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+               goto rpn_out;
+       }
++      rpn = skb_pull_data(skb, sizeof(*rpn));
++      if (!rpn)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rpn->dlci);
++
++      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
++             dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
++             rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++
++      if (!cr)
++              return 0;
++
+       /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+        * no parity, no flow control lines, normal XON/XOFF chars */
+@@ -1589,9 +1608,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_rls *rls = (void *) skb->data;
+-      u8 dlci = __get_dlci(rls->dlci);
++      struct rfcomm_rls *rls;
++      u8 dlci;
++      rls = skb_pull_data(skb, sizeof(*rls));
++      if (!rls)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rls->dlci);
+       BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+       if (!cr)
+@@ -1608,10 +1632,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_msc *msc = (void *) skb->data;
++      struct rfcomm_msc *msc;
+       struct rfcomm_dlc *d;
+-      u8 dlci = __get_dlci(msc->dlci);
++      u8 dlci;
++
++      msc = skb_pull_data(skb, sizeof(*msc));
++      if (!msc)
++              return -EILSEQ;
++      dlci = __get_dlci(msc->dlci);
+       BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
+       d = rfcomm_dlc_get(s, dlci);
+@@ -1644,17 +1673,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
+ {
+-      struct rfcomm_mcc *mcc = (void *) skb->data;
++      struct rfcomm_mcc *mcc;
+       u8 type, cr, len;
++      mcc = skb_pull_data(skb, sizeof(*mcc));
++      if (!mcc)
++              return -EILSEQ;
++
+       cr   = __test_cr(mcc->type);
+       type = __get_mcc_type(mcc->type);
+       len  = __get_mcc_len(mcc->len);
+       BT_DBG("%p type 0x%x cr %d", s, type, cr);
+-      skb_pull(skb, 2);
+-
+       switch (type) {
+       case RFCOMM_PN:
+               rfcomm_recv_pn(s, cr, skb);
+-- 
+2.53.0
+
diff --git a/queue-6.12/devlink-release-nested-relation-on-devlink-free.patch b/queue-6.12/devlink-release-nested-relation-on-devlink-free.patch
new file mode 100644 (file)
index 0000000..f42ac8a
--- /dev/null
@@ -0,0 +1,49 @@
+From eb6ef0dddb7fa0b97f5e591f8a57d1b8a188890d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 22:14:10 +0300
+Subject: devlink: Release nested relation on devlink free
+
+From: Mark Bloch <mbloch@nvidia.com>
+
+[ Upstream commit 3522b21fd7e1863d0734537737bd59f1b90d0190 ]
+
+devlink relation state is normally released from devl_unregister(), which
+calls devlink_rel_put(). This misses devlink instances that get a nested
+relation before registration and then fail probe before devl_register() is
+reached.
+
+That flow can happen for SFs. The child devlink gets linked to its
+parent before registration, then a later probe error calls devlink_free()
+directly. Since the instance was never registered, devl_unregister() is not
+called and devlink->rel is leaked.
+
+Release any pending relation from devlink_free() as well. The registered
+path is unchanged because devl_unregister() already clears devlink->rel
+before devlink_free() runs.
+
+Fixes: c137743bce02 ("devlink: introduce object and nested devlink relationship infra")
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://patch.msgid.link/20260528191411.3270532-1-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/devlink/core.c b/net/devlink/core.c
+index 7203c39532fcc3..5f62fe5d2aa883 100644
+--- a/net/devlink/core.c
++++ b/net/devlink/core.c
+@@ -469,6 +469,8 @@ void devlink_free(struct devlink *devlink)
+ {
+       ASSERT_DEVLINK_NOT_REGISTERED(devlink);
++      devlink_rel_put(devlink);
++
+       WARN_ON(!list_empty(&devlink->trap_policer_list));
+       WARN_ON(!list_empty(&devlink->trap_group_list));
+       WARN_ON(!list_empty(&devlink->trap_list));
+-- 
+2.53.0
+
diff --git a/queue-6.12/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-6.12/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..9e62ded
--- /dev/null
@@ -0,0 +1,71 @@
+From 7cc42b60e028e84ed2da9ca60c9b876b647d4476 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index d81a87142cacfa..5f48bcbdaf4351 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1590,18 +1590,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-6.12/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-6.12/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..73913fd
--- /dev/null
@@ -0,0 +1,53 @@
+From 28b8bb7cffae74a80146153caa47370e1334423d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index 825728c356ffbe..eb81a4a57905a7 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -166,6 +166,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-6.12/erofs-add-sysfs-node-to-drop-internal-caches.patch b/queue-6.12/erofs-add-sysfs-node-to-drop-internal-caches.patch
new file mode 100644 (file)
index 0000000..9628f5e
--- /dev/null
@@ -0,0 +1,119 @@
+From e88f0809bbeb7a75baa767eb7708ff8510998a1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Nov 2024 21:11:48 -0700
+Subject: erofs: add sysfs node to drop internal caches
+
+From: Chunhai Guo <guochunhai@vivo.com>
+
+[ Upstream commit db80b98305f73ca83891e4228ead5f0324118b00 ]
+
+Add a sysfs node to drop compression-related caches, currently used to
+drop in-memory pclusters and cached compressed folios.
+
+Signed-off-by: Chunhai Guo <guochunhai@vivo.com>
+Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20241113041148.749129-1-guochunhai@vivo.com
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Stable-dep-of: 1aee05e814d2 ("erofs: fix use-after-free on sbi->sync_decompress")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/ABI/testing/sysfs-fs-erofs | 11 +++++++++++
+ fs/erofs/internal.h                      |  2 ++
+ fs/erofs/sysfs.c                         | 17 +++++++++++++++++
+ fs/erofs/zdata.c                         |  1 -
+ 4 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/ABI/testing/sysfs-fs-erofs b/Documentation/ABI/testing/sysfs-fs-erofs
+index 284224d1b56fe1..b134146d735bc5 100644
+--- a/Documentation/ABI/testing/sysfs-fs-erofs
++++ b/Documentation/ABI/testing/sysfs-fs-erofs
+@@ -16,3 +16,14 @@ Description:        Control strategy of sync decompression:
+                 readahead on atomic contexts only.
+               - 1 (force on): enable for readpage and readahead.
+               - 2 (force off): disable for all situations.
++
++What:         /sys/fs/erofs/<disk>/drop_caches
++Date:         November 2024
++Contact:      "Guo Chunhai" <guochunhai@vivo.com>
++Description:  Writing to this will drop compression-related caches,
++              currently used to drop in-memory pclusters and cached
++              compressed folios:
++
++              - 1 : invalidate cached compressed folios
++              - 2 : drop in-memory pclusters
++              - 3 : drop in-memory pclusters and cached compressed folios
+diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
+index 1c003412677ef6..24e01d9135c60d 100644
+--- a/fs/erofs/internal.h
++++ b/fs/erofs/internal.h
+@@ -443,6 +443,8 @@ static inline void erofs_pagepool_add(struct page **pagepool, struct page *page)
+ void erofs_release_pages(struct page **pagepool);
+ #ifdef CONFIG_EROFS_FS_ZIP
++#define MNGD_MAPPING(sbi)     ((sbi)->managed_cache->i_mapping)
++
+ extern atomic_long_t erofs_global_shrink_cnt;
+ void erofs_shrinker_register(struct super_block *sb);
+ void erofs_shrinker_unregister(struct super_block *sb);
+diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
+index 63cffd0fd26195..19d586273b7091 100644
+--- a/fs/erofs/sysfs.c
++++ b/fs/erofs/sysfs.c
+@@ -10,6 +10,7 @@
+ enum {
+       attr_feature,
++      attr_drop_caches,
+       attr_pointer_ui,
+       attr_pointer_bool,
+ };
+@@ -57,11 +58,13 @@ static struct erofs_attr erofs_attr_##_name = {                    \
+ #ifdef CONFIG_EROFS_FS_ZIP
+ EROFS_ATTR_RW_UI(sync_decompress, erofs_mount_opts);
++EROFS_ATTR_FUNC(drop_caches, 0200);
+ #endif
+ static struct attribute *erofs_attrs[] = {
+ #ifdef CONFIG_EROFS_FS_ZIP
+       ATTR_LIST(sync_decompress),
++      ATTR_LIST(drop_caches),
+ #endif
+       NULL,
+ };
+@@ -163,6 +166,20 @@ static ssize_t erofs_attr_store(struct kobject *kobj, struct attribute *attr,
+                       return -EINVAL;
+               *(bool *)ptr = !!t;
+               return len;
++#ifdef CONFIG_EROFS_FS_ZIP
++      case attr_drop_caches:
++              ret = kstrtoul(skip_spaces(buf), 0, &t);
++              if (ret)
++                      return ret;
++              if (t < 1 || t > 3)
++                      return -EINVAL;
++
++              if (t & 2)
++                      z_erofs_shrink_scan(sbi, ~0UL);
++              if (t & 1)
++                      invalidate_mapping_pages(MNGD_MAPPING(sbi), 0, -1);
++              return len;
++#endif
+       }
+       return 0;
+ }
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index a81b6e6aee59ad..8192eb9b23bc7b 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -109,7 +109,6 @@ static inline unsigned int z_erofs_pclusterpages(struct z_erofs_pcluster *pcl)
+       return PAGE_ALIGN(pcl->pclustersize) >> PAGE_SHIFT;
+ }
+-#define MNGD_MAPPING(sbi)     ((sbi)->managed_cache->i_mapping)
+ static bool erofs_folio_is_managed(struct erofs_sb_info *sbi, struct folio *fo)
+ {
+       return fo->mapping == MNGD_MAPPING(sbi);
+-- 
+2.53.0
+
diff --git a/queue-6.12/erofs-fix-use-after-free-on-sbi-sync_decompress.patch b/queue-6.12/erofs-fix-use-after-free-on-sbi-sync_decompress.patch
new file mode 100644 (file)
index 0000000..c5f501e
--- /dev/null
@@ -0,0 +1,66 @@
+From c5ea0d1c9c4865af55344a839ed4f6e9e0c3f594 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:27:16 +0800
+Subject: erofs: fix use-after-free on sbi->sync_decompress
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+[ Upstream commit 1aee05e814d292064bf5fa15733741040cdc48ba ]
+
+z_erofs_decompress_kickoff() can race with filesystem unmount, causing
+a use-after-free on sbi->sync_decompress.
+
+When I/O completes, z_erofs_endio() calls z_erofs_decompress_kickoff()
+to queue z_erofs_decompressqueue_work() asynchronously. Then, after all
+folios are unlocked, unmount workflow can proceed and sbi will be freed
+before accessing to sbi->sync_decompress.
+
+Thread (unmount)        I/O completion        kworker
+                        queue_work
+                                              z_erofs_decompressqueue_work
+                                               (all folios are unlocked)
+cleanup_mnt
+ ..
+ erofs_kill_sb
+  erofs_sb_free
+   kfree(sbi)
+                        access sbi->sync_decompress  // UAF!!
+
+Fixes: 40452ffca3c1 ("erofs: add sysfs node to control sync decompression strategy")
+Reported-by: syzbot+52bae5c495dbe261a0bc@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=52bae5c495dbe261a0bc
+Reviewed-by: Chao Yu <chao@kernel.org>
+Reviewed-by: Jianan Huang <jnhuang95@gmail.com>
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/erofs/zdata.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index da421fe310df11..d625e3be9ec6ce 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -1424,6 +1424,9 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+       if (atomic_add_return(bios, &io->pending_bios))
+               return;
+       if (z_erofs_in_atomic()) {
++              /* See `sync_decompress` in sysfs-fs-erofs for more details */
++              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
++                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+ #ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
+               struct kthread_worker *worker;
+@@ -1440,9 +1443,6 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+ #else
+               queue_work(z_erofs_workqueue, &io->u.work);
+ #endif
+-              /* See `sync_decompress` in sysfs-fs-erofs for more details */
+-              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
+-                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+               return;
+       }
+       gfp_flag = memalloc_noio_save();
+-- 
+2.53.0
+
diff --git a/queue-6.12/erofs-tidy-up-synchronous-decompression.patch b/queue-6.12/erofs-tidy-up-synchronous-decompression.patch
new file mode 100644 (file)
index 0000000..4e60b60
--- /dev/null
@@ -0,0 +1,193 @@
+From f5be4014fefa035037f8e1aed49d051695c9efd6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 11:43:30 +0800
+Subject: erofs: tidy up synchronous decompression
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+[ Upstream commit cc831ab33644088c1eef78936de24701014d520a ]
+
+ - Get rid of `sbi->opt.max_sync_decompress_pages` since it's fixed as
+   3 all the time;
+
+ - Add Z_EROFS_MAX_SYNC_DECOMPRESS_BYTES in bytes instead of in pages,
+   since for non-4K pages, 3-page limitation makes no sense;
+
+ - Move `sync_decompress` to sbi to avoid unexpected remount impact;
+
+ - Fold z_erofs_is_sync_decompress() into its caller;
+
+ - Better description of sysfs entry `sync_decompress`.
+
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Stable-dep-of: 1aee05e814d2 ("erofs: fix use-after-free on sbi->sync_decompress")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/ABI/testing/sysfs-fs-erofs | 14 ++++++----
+ fs/erofs/internal.h                      |  5 +---
+ fs/erofs/super.c                         |  3 +-
+ fs/erofs/sysfs.c                         |  2 +-
+ fs/erofs/zdata.c                         | 35 +++++++++---------------
+ 5 files changed, 25 insertions(+), 34 deletions(-)
+
+diff --git a/Documentation/ABI/testing/sysfs-fs-erofs b/Documentation/ABI/testing/sysfs-fs-erofs
+index b134146d735bc5..d76de22b6ef31c 100644
+--- a/Documentation/ABI/testing/sysfs-fs-erofs
++++ b/Documentation/ABI/testing/sysfs-fs-erofs
+@@ -10,12 +10,16 @@ Description:       Shows all enabled kernel features.
+ What:         /sys/fs/erofs/<disk>/sync_decompress
+ Date:         November 2021
+ Contact:      "Huang Jianan" <huangjianan@oppo.com>
+-Description:  Control strategy of sync decompression:
++Description:  Control strategy of synchronous decompression. Synchronous
++              decompression tries to decompress in the reader thread for
++              synchronous reads and small asynchronous reads (<= 12 KiB):
+-              - 0 (default, auto): enable for readpage, and enable for
+-                readahead on atomic contexts only.
+-              - 1 (force on): enable for readpage and readahead.
+-              - 2 (force off): disable for all situations.
++              - 0 (auto, default): apply to synchronous reads only, but will
++                                   switch to 1 (force on) if any decompression
++                                   request is detected in atomic contexts;
++              - 1 (force on): apply to synchronous reads and small
++                              asynchronous reads;
++              - 2 (force off): disable synchronous decompression completely.
+ What:         /sys/fs/erofs/<disk>/drop_caches
+ Date:         November 2024
+diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
+index 24e01d9135c60d..89dfb3736daa41 100644
+--- a/fs/erofs/internal.h
++++ b/fs/erofs/internal.h
+@@ -66,10 +66,6 @@ enum {
+ struct erofs_mount_opts {
+       /* current strategy of how to use managed cache */
+       unsigned char cache_strategy;
+-      /* strategy of sync decompression (0 - auto, 1 - force on, 2 - force off) */
+-      unsigned int sync_decompress;
+-      /* threshold for decompression synchronously */
+-      unsigned int max_sync_decompress_pages;
+       unsigned int mount_opt;
+ };
+@@ -123,6 +119,7 @@ struct erofs_sb_info {
+       /* managed XArray arranged in physical block number */
+       struct xarray managed_pslots;
++      unsigned int sync_decompress;   /* strategy for sync decompression */
+       unsigned int shrinker_run_no;
+       u16 available_compr_algs;
+diff --git a/fs/erofs/super.c b/fs/erofs/super.c
+index bc968cf812bac4..1640ebc26ac9c4 100644
+--- a/fs/erofs/super.c
++++ b/fs/erofs/super.c
+@@ -370,8 +370,7 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
+ {
+ #ifdef CONFIG_EROFS_FS_ZIP
+       sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
+-      sbi->opt.max_sync_decompress_pages = 3;
+-      sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
++      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
+ #endif
+ #ifdef CONFIG_EROFS_FS_XATTR
+       set_opt(&sbi->opt, XATTR_USER);
+diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
+index 19d586273b7091..3fbce0864a66f0 100644
+--- a/fs/erofs/sysfs.c
++++ b/fs/erofs/sysfs.c
+@@ -57,7 +57,7 @@ static struct erofs_attr erofs_attr_##_name = {                      \
+ #define ATTR_LIST(name) (&erofs_attr_##name.attr)
+ #ifdef CONFIG_EROFS_FS_ZIP
+-EROFS_ATTR_RW_UI(sync_decompress, erofs_mount_opts);
++EROFS_ATTR_RW_UI(sync_decompress, erofs_sb_info);
+ EROFS_ATTR_FUNC(drop_caches, 0200);
+ #endif
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index 8192eb9b23bc7b..da421fe310df11 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -9,6 +9,7 @@
+ #include <linux/cpuhotplug.h>
+ #include <trace/events/erofs.h>
++#define Z_EROFS_MAX_SYNC_DECOMPRESS_BYTES     12288
+ #define Z_EROFS_PCLUSTER_MAX_PAGES    (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE)
+ #define Z_EROFS_INLINE_BVECS          2
+@@ -1077,21 +1078,6 @@ static int z_erofs_scan_folio(struct z_erofs_frontend *f,
+       return err;
+ }
+-static bool z_erofs_is_sync_decompress(struct erofs_sb_info *sbi,
+-                                     unsigned int readahead_pages)
+-{
+-      /* auto: enable for read_folio, disable for readahead */
+-      if ((sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO) &&
+-          !readahead_pages)
+-              return true;
+-
+-      if ((sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_FORCE_ON) &&
+-          (readahead_pages <= sbi->opt.max_sync_decompress_pages))
+-              return true;
+-
+-      return false;
+-}
+-
+ static bool z_erofs_page_is_invalidated(struct page *page)
+ {
+       return !page_folio(page)->mapping && !z_erofs_is_shortlived_page(page);
+@@ -1454,9 +1440,9 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+ #else
+               queue_work(z_erofs_workqueue, &io->u.work);
+ #endif
+-              /* enable sync decompression for readahead */
+-              if (sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
+-                      sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
++              /* See `sync_decompress` in sysfs-fs-erofs for more details */
++              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
++                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+               return;
+       }
+       gfp_flag = memalloc_noio_save();
+@@ -1777,16 +1763,21 @@ static void z_erofs_submit_queue(struct z_erofs_frontend *f,
+       z_erofs_decompress_kickoff(q[JQ_SUBMIT], nr_bios);
+ }
+-static int z_erofs_runqueue(struct z_erofs_frontend *f, unsigned int rapages)
++static int z_erofs_runqueue(struct z_erofs_frontend *f, unsigned int rabytes)
+ {
+       struct z_erofs_decompressqueue io[NR_JOBQUEUES];
+       struct erofs_sb_info *sbi = EROFS_I_SB(f->inode);
+-      bool force_fg = z_erofs_is_sync_decompress(sbi, rapages);
++      int syncmode = sbi->sync_decompress;
++      bool force_fg;
+       int err;
++      force_fg = (syncmode == EROFS_SYNC_DECOMPRESS_AUTO && !rabytes) ||
++              (syncmode == EROFS_SYNC_DECOMPRESS_FORCE_ON &&
++                      (rabytes <= Z_EROFS_MAX_SYNC_DECOMPRESS_BYTES));
++
+       if (f->head == Z_EROFS_PCLUSTER_TAIL)
+               return 0;
+-      z_erofs_submit_queue(f, io, &force_fg, !!rapages);
++      z_erofs_submit_queue(f, io, &force_fg, !!rabytes);
+       /* handle bypass queue (no i/o pclusters) immediately */
+       err = z_erofs_decompress_queue(&io[JQ_BYPASS], &f->pagepool);
+@@ -1907,7 +1898,7 @@ static void z_erofs_readahead(struct readahead_control *rac)
+       z_erofs_pcluster_readmore(&f, rac, false);
+       z_erofs_pcluster_end(&f);
+-      (void)z_erofs_runqueue(&f, nrpages);
++      (void)z_erofs_runqueue(&f, nrpages << PAGE_SHIFT);
+       erofs_put_metabuf(&f.map.buf);
+       erofs_release_pages(&f.pagepool);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/hsr-remove-warn_once-in-hsr_addr_is_self.patch b/queue-6.12/hsr-remove-warn_once-in-hsr_addr_is_self.patch
new file mode 100644 (file)
index 0000000..2d29efa
--- /dev/null
@@ -0,0 +1,109 @@
+From 5982f1924f07ceb926e9be9b13b7b77780d3d5f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 May 2026 06:42:58 +0000
+Subject: hsr: Remove WARN_ONCE() in hsr_addr_is_self().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit afd0f17ca46258cec3a5cc48b8df9327fe772490 ]
+
+syzbot reported the warning [0] in hsr_addr_is_self(),
+whose assumption is simply wrong.
+
+hsr->self_node is cleared in hsr_del_self_node(), which
+is called from hsr_dellink().
+
+Since dev->rtnl_link_ops->dellink() is called before
+unregister_netdevice_many(), there is a window when
+user can find the device but without hsr->self_node.
+
+Let's remove WARN_ONCE() in hsr_addr_is_self().
+
+[0]:
+HSR: No self node
+WARNING: net/hsr/hsr_framereg.c:39 at hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39, CPU#0: syz.4.16848/17220
+Modules linked in:
+CPU: 0 UID: 0 PID: 17220 Comm: syz.4.16848 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39
+Code: 33 2f 41 0f b7 dd 89 ee 09 de 31 ff e8 c8 b4 c6 f6 09 dd 74 54 e8 0f b0 c6 f6 31 ed eb 53 e8 06 b0 c6 f6 48 8d 3d 2f 50 9c 04 <67> 48 0f b9 3a 31 ed eb 42 e8 c1 13 1f 00 89 c5 31 ff 89 c6 e8 96
+RSP: 0018:ffffc900041c70e0 EFLAGS: 00010283
+RAX: ffffffff8afdc6ca RBX: ffffffff8afdc4e6 RCX: 0000000000080000
+RDX: ffffc90010493000 RSI: 0000000000000948 RDI: ffffffff8f9a1700
+RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
+R10: ffffc900041c71e8 R11: fffff52000838e3f R12: dffffc0000000000
+R13: ffff888041f9e3c0 R14: ffff888086ee3802 R15: 0000000000000000
+FS:  00007f6fe985d6c0(0000) GS:ffff888126176000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f80bd437dac CR3: 0000000025096000 CR4: 00000000003526f0
+DR0: ffffffffffffffff DR1: 00000000000001f8 DR2: 0000000000000002
+DR3: ffffffffefffff15 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ check_local_dest net/hsr/hsr_forward.c:592 [inline]
+ fill_frame_info net/hsr/hsr_forward.c:728 [inline]
+ hsr_forward_skb+0xa11/0x2a80 net/hsr/hsr_forward.c:739
+ hsr_dev_xmit+0x253/0x370 net/hsr/hsr_device.c:236
+ __netdev_start_xmit include/linux/netdevice.h:5368 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5377 [inline]
+ xmit_one net/core/dev.c:3888 [inline]
+ dev_hard_start_xmit+0x2df/0x860 net/core/dev.c:3904
+ __dev_queue_xmit+0x1428/0x3900 net/core/dev.c:4870
+ neigh_output include/net/neighbour.h:556 [inline]
+ ip_finish_output2+0xcec/0x10b0 net/ipv4/ip_output.c:237
+ ip_send_skb net/ipv4/ip_output.c:1510 [inline]
+ ip_push_pending_frames+0x8b/0x110 net/ipv4/ip_output.c:1530
+ raw_sendmsg+0x1547/0x1a50 net/ipv4/raw.c:659
+ sock_sendmsg_nosec net/socket.c:787 [inline]
+ __sock_sendmsg net/socket.c:802 [inline]
+ ____sys_sendmsg+0x7da/0x9c0 net/socket.c:2698
+ ___sys_sendmsg+0x2a5/0x360 net/socket.c:2752
+ __sys_sendmsg net/socket.c:2784 [inline]
+ __do_sys_sendmsg net/socket.c:2789 [inline]
+ __se_sys_sendmsg net/socket.c:2787 [inline]
+ __x64_sys_sendmsg+0x1c3/0x2a0 net/socket.c:2787
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f6feb62ce59
+Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f6fe985d028 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f6feb8a6090 RCX: 00007f6feb62ce59
+RDX: 0000000000000000 RSI: 0000200000000000 RDI: 0000000000000004
+RBP: 00007f6feb6c2d6f R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007f6feb8a6128 R14: 00007f6feb8a6090 R15: 00007ffcf01cc488
+ </TASK>
+
+Fixes: f266a683a480 ("net/hsr: Better frame dispatch")
+Reported-by: syzbot+652670cf249077eb498b@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1a861e.b111c304.35cd64.0016.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260530064300.340793-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_framereg.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index 47faa8b4aaa901..2ba586cb829ff3 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -52,10 +52,8 @@ bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr)
+       rcu_read_lock();
+       sn = rcu_dereference(hsr->self_node);
+-      if (!sn) {
+-              WARN_ONCE(1, "HSR: No self node\n");
++      if (!sn)
+               goto out;
+-      }
+       if (ether_addr_equal(addr, sn->macaddress_A) ||
+           ether_addr_equal(addr, sn->macaddress_B))
+-- 
+2.53.0
+
diff --git a/queue-6.12/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-6.12/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..e5814c4
--- /dev/null
@@ -0,0 +1,56 @@
+From 25d7b310a797c7ad6b8e236adde87343b7d76159 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-6.12/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-6.12/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..751efbb
--- /dev/null
@@ -0,0 +1,54 @@
+From 0c251db973e2f7e35577c6b084e41217f10a3a45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index 3d154bc7e1f2e5..6527c3e88de36c 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -530,6 +530,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.12/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch b/queue-6.12/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
new file mode 100644 (file)
index 0000000..e3796f9
--- /dev/null
@@ -0,0 +1,107 @@
+From f9ac9192b424b7eab8e2819013c2d9a82cb473d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 13:18:11 +0300
+Subject: ipv6: mcast: Fix use-after-free when processing MLD queries
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ]
+
+When processing an MLD query, a pointer to the multicast group address
+is retrieved when initially parsing the packet. This pointer is later
+dereferenced without being reloaded despite the fact that the skb header
+might have been reallocated following the pskb_may_pull() calls, leading
+to a use-after-free [1].
+
+Fix by copying the multicast group address when the packet is initially
+parsed.
+
+[1]
+BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512)
+Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
+
+Workqueue: mld mld_query_work
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+print_address_description.constprop.0 (mm/kasan/report.c:378)
+print_report (mm/kasan/report.c:482)
+kasan_report (mm/kasan/report.c:595)
+__mld_query_work (net/ipv6/mcast.c:1512)
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+</TASK>
+
+[...]
+
+Freed by task 118:
+kasan_save_stack (mm/kasan/common.c:57)
+kasan_save_track (mm/kasan/common.c:78)
+kasan_save_free_info (mm/kasan/generic.c:584)
+__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
+kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566)
+pskb_expand_head (net/core/skbuff.c:2335)
+__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4))
+__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+
+Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Reviewed-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/mcast.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index e2a11a2f3b255d..b769e856a068d2 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1393,9 +1393,9 @@ void igmp6_event_query(struct sk_buff *skb)
+ static void __mld_query_work(struct sk_buff *skb)
+ {
+       struct mld2_query *mlh2 = NULL;
+-      const struct in6_addr *group;
+       unsigned long max_delay;
+       struct inet6_dev *idev;
++      struct in6_addr group;
+       struct ifmcaddr6 *ma;
+       struct mld_msg *mld;
+       int group_type;
+@@ -1427,8 +1427,8 @@ static void __mld_query_work(struct sk_buff *skb)
+               goto kfree_skb;
+       mld = (struct mld_msg *)icmp6_hdr(skb);
+-      group = &mld->mld_mca;
+-      group_type = ipv6_addr_type(group);
++      group = mld->mld_mca;
++      group_type = ipv6_addr_type(&group);
+       if (group_type != IPV6_ADDR_ANY &&
+           !(group_type&IPV6_ADDR_MULTICAST))
+@@ -1478,7 +1478,7 @@ static void __mld_query_work(struct sk_buff *skb)
+               }
+       } else {
+               for_each_mc_mclock(idev, ma) {
+-                      if (!ipv6_addr_equal(group, &ma->mca_addr))
++                      if (!ipv6_addr_equal(&group, &ma->mca_addr))
+                               continue;
+                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                               /* gsquery <- gsquery && mark */
+-- 
+2.53.0
+
diff --git a/queue-6.12/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-6.12/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..2d87231
--- /dev/null
@@ -0,0 +1,127 @@
+From a8b1f2e2024fc33ea8dab38f20ed5b7832dd6cf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index ff406ef4fd4aab..d70268cf1af82e 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1506,8 +1506,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index efa845ce616d9c..fb638758594d51 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1496,7 +1496,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1558,9 +1558,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1568,6 +1567,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1624,7 +1627,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index d4903723be7e90..49b2e5d2b2c837 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch b/queue-6.12/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
new file mode 100644 (file)
index 0000000..ac63918
--- /dev/null
@@ -0,0 +1,75 @@
+From ecece5221c7a01e559789a22fa378f9626230eb5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 00:00:00 +0000
+Subject: ksmbd: fix NULL-deref of opinfo->conn in oplock/lease break notifiers
+
+From: Gil Portnoy <dddhkts1@gmail.com>
+
+[ Upstream commit b003086d76968298f22e7cf62239833b5a3a06b1 ]
+
+smb2_oplock_break_noti() and smb2_lease_break_noti() read opinfo->conn
+into a local with neither READ_ONCE() nor a NULL check.  Both run from
+oplock_break() after opinfo_get_list() has dropped ci->m_lock, so a
+concurrent SMB2 LOGOFF (session_fd_check()) can set op->conn = NULL
+under ci->m_lock within that window.  ksmbd_conn_r_count_inc(conn) then
+writes through NULL at offset 0xc4 -- a remotely triggerable oops.
+
+Guard both reads the way compare_guid_key() already does: read
+opinfo->conn with READ_ONCE() and return early if it is NULL, before
+allocating the work struct so nothing leaks.  A NULL conn means the
+client is gone and the break is moot, so return 0; oplock_break() treats
+that as success and runs the normal teardown.
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Assisted-by: Henry (Claude):claude-opus-4
+Signed-off-by: Gil Portnoy <dddhkts1@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/oplock.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index a84c01bceb8ba2..6454c7a4baa450 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -714,11 +714,16 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
+  */
+ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct oplock_break_info *br_info;
+       int ret = 0;
+-      struct ksmbd_work *work = ksmbd_alloc_work_struct();
++      struct ksmbd_work *work;
++
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++      work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+@@ -818,11 +823,15 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
+  */
+ static int smb2_lease_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct ksmbd_work *work;
+       struct lease_break_info *br_info;
+       struct lease *lease = opinfo->o_lease;
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++
+       work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+-- 
+2.53.0
+
diff --git a/queue-6.12/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch b/queue-6.12/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch
new file mode 100644 (file)
index 0000000..5831392
--- /dev/null
@@ -0,0 +1,176 @@
+From b9866e7da1744a2e8c0aeb89a2429248b5f818ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:36:29 +0000
+Subject: l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit a213a8950414c684999dcf03edeea6c46ede172e ]
+
+pppol2tp_ioctl() read sock->sk->sk_user_data directly without any
+locks or reference counting.  If a controllable sleep was induced during
+copy_from_user() (e.g. via a userfaultfd page fault sleep), a concurrent
+socket close could trigger pppol2tp_session_close() asynchronously.  This
+frees the l2tp_session structure via the l2tp_session_del_work workqueue.
+Upon resuming, the ioctl thread dereferences the stale session pointer,
+resulting in a Use-After-Free (UAF).
+
+Fix this by securely fetching the session reference using the RCU-safe,
+refcounted helper pppol2tp_sock_to_session(sk) on entry.  This locks the
+session's refcount across the sleep.  We structured the function to exit
+via standard err breaks, guaranteeing that l2tp_session_put() is cleanly
+called on all return paths to drop the reference.
+
+To preserve existing behavior we validate the session and its magic
+signature only for the specific L2TP commands that require it.  This
+ensures that generic/unknown ioctls called on an unconnected socket
+still return -ENOIOCTLCMD and correctly fall back to generic handlers
+(e.g. in sock_do_ioctl()).
+
+Signed-off-by: Lee Jones <lee@kernel.org>
+Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts")
+Link: https://patch.msgid.link/20260527133630.2120612-1-lee@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_ppp.c | 82 +++++++++++++++++++++++++++------------------
+ 1 file changed, 50 insertions(+), 32 deletions(-)
+
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index 16c514f628eaca..bf78edee1ef8a7 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -1043,64 +1043,76 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+ {
+       struct pppol2tp_ioc_stats stats;
+       struct l2tp_session *session;
++      int err = 0;
++
++      session = pppol2tp_sock_to_session(sock->sk);
++      /* Validate session presence and magic integrity ONLY for commands
++       * that belong to L2TP and require a valid session.
++       */
+       switch (cmd) {
+       case PPPIOCGMRU:
+       case PPPIOCGFLAGS:
+-              session = sock->sk->sk_user_data;
++      case PPPIOCSMRU:
++      case PPPIOCSFLAGS:
++      case PPPIOCGL2TPSTATS:
+               if (!session)
+                       return -ENOTCONN;
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
++              if (session->magic != L2TP_SESSION_MAGIC) {
++                      l2tp_session_put(session);
+                       return -EBADF;
++              }
++              break;
++      default:
++              break;
++      }
++      switch (cmd) {
++      case PPPIOCGMRU:
++      case PPPIOCGFLAGS:
+               /* Not defined for tunnels */
+-              if (!session->session_id && !session->peer_session_id)
+-                      return -ENOSYS;
++              if (!session->session_id && !session->peer_session_id) {
++                      err = -ENOSYS;
++                      break;
++              }
+-              if (put_user(0, (int __user *)arg))
+-                      return -EFAULT;
++              if (put_user(0, (int __user *)arg)) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       case PPPIOCSMRU:
+       case PPPIOCSFLAGS:
+-              session = sock->sk->sk_user_data;
+-              if (!session)
+-                      return -ENOTCONN;
+-
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
+-                      return -EBADF;
+-
+               /* Not defined for tunnels */
+-              if (!session->session_id && !session->peer_session_id)
+-                      return -ENOSYS;
++              if (!session->session_id && !session->peer_session_id) {
++                      err = -ENOSYS;
++                      break;
++              }
+-              if (!access_ok((int __user *)arg, sizeof(int)))
+-                      return -EFAULT;
++              if (!access_ok((int __user *)arg, sizeof(int))) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       case PPPIOCGL2TPSTATS:
+-              session = sock->sk->sk_user_data;
+-              if (!session)
+-                      return -ENOTCONN;
+-
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
+-                      return -EBADF;
+-
+               /* Session 0 represents the parent tunnel */
+               if (!session->session_id && !session->peer_session_id) {
+                       u32 session_id;
+-                      int err;
+                       if (copy_from_user(&stats, (void __user *)arg,
+-                                         sizeof(stats)))
+-                              return -EFAULT;
++                                         sizeof(stats))) {
++                              err = -EFAULT;
++                              break;
++                      }
+                       session_id = stats.session_id;
+                       err = pppol2tp_tunnel_copy_stats(&stats,
+                                                        session->tunnel);
+                       if (err < 0)
+-                              return err;
++                              break;
+                       stats.session_id = session_id;
+               } else {
+@@ -1110,15 +1122,21 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+               stats.tunnel_id = session->tunnel->tunnel_id;
+               stats.using_ipsec = l2tp_tunnel_uses_xfrm(session->tunnel);
+-              if (copy_to_user((void __user *)arg, &stats, sizeof(stats)))
+-                      return -EFAULT;
++              if (copy_to_user((void __user *)arg, &stats, sizeof(stats))) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       default:
+-              return -ENOIOCTLCMD;
++              err = -ENOIOCTLCMD;
++              break;
+       }
+-      return 0;
++      if (session)
++              l2tp_session_put(session);
++
++      return err;
+ }
+ /*****************************************************************************
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-6.12/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..cfe340a
--- /dev/null
@@ -0,0 +1,79 @@
+From 0302e6f01dbc3950a6c84e5ea700535c49ea4d6d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index e0c96d0da8d599..8d08ace05fb8e8 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -703,6 +703,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -753,6 +759,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-annotate-sk-sk_write_space-for-udp-sockmap.patch b/queue-6.12/net-annotate-sk-sk_write_space-for-udp-sockmap.patch
new file mode 100644 (file)
index 0000000..b42b196
--- /dev/null
@@ -0,0 +1,60 @@
+From a846df0ff882ce383c5d90ef82d8419b4b7c24fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:39:23 +0000
+Subject: net: Annotate sk->sk_write_space() for UDP SOCKMAP.
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit b748765019fe9e9234660327090fc1a9665cdbdd ]
+
+UDP TX skb->destructor() is sock_wfree(), and UDP holds lock_sock()
+only for UDP_CORK / MSG_MORE sendmsg().
+
+Otherwise, sk->sk_write_space() may be read locklessly while SOCKMAP
+rewrites sk->sk_write_space().
+
+Let's use WRITE_ONCE() and READ_ONCE() for sk->sk_write_space().
+
+Note that the write side is annotated by commit 2ef2b20cf4e0
+("net: annotate data-races around sk->sk_{data_ready,write_space}").
+
+Fixes: 7b98cd42b049 ("bpf: sockmap: Add UDP support")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://patch.msgid.link/20260529193941.3897256-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 58f3f0d979540f..7b6ed7c85a58cc 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2591,8 +2591,12 @@ void sock_wfree(struct sk_buff *skb)
+       bool free;
+       if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
++              void (*sk_write_space)(struct sock *sk);
++
++              sk_write_space = READ_ONCE(sk->sk_write_space);
++
+               if (sock_flag(sk, SOCK_RCU_FREE) &&
+-                  sk->sk_write_space == sock_def_write_space) {
++                  sk_write_space == sock_def_write_space) {
+                       rcu_read_lock();
+                       free = refcount_sub_and_test(len, &sk->sk_wmem_alloc);
+                       sock_def_write_space_wfree(sk);
+@@ -2607,7 +2611,7 @@ void sock_wfree(struct sk_buff *skb)
+                * after sk_write_space() call
+                */
+               WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
+-              sk->sk_write_space(sk);
++              sk_write_space(sk);
+               len = 1;
+       }
+       /*
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch b/queue-6.12/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
new file mode 100644 (file)
index 0000000..aba3a72
--- /dev/null
@@ -0,0 +1,48 @@
+From 693009237798e050591bf129020f5a040d75f8bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:21:05 +0200
+Subject: net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst
+ teardown
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit 80df409e1a483676826a6c66e693dba6ac507751 ]
+
+mtk_free_dev() calls metadata_dst_free() which frees the metadata_dst
+with kfree() immediately, bypassing the RCU grace period.
+In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
+the skb to the metadata_dst. This function requires RCU read-side
+protection and the dst must remain valid until all RCU readers complete.
+Since metadata_dst_free() calls kfree() directly, a use-after-free can
+occur if any skb still holds a noref pointer to the dst when the driver
+tears it down.
+Replace metadata_dst_free() with dst_release() which properly goes
+through the refcount path: when the refcount drops to zero, it schedules
+the actual free via call_rcu_hurry(), ensuring all RCU readers have
+completed before the memory is freed.
+
+Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-2-3aaa99d83351@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index 7406b706fb7530..ebf5432cb328d7 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -4287,7 +4287,7 @@ static int mtk_free_dev(struct mtk_eth *eth)
+       for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
+               if (!eth->dsa_meta[i])
+                       break;
+-              metadata_dst_free(eth->dsa_meta[i]);
++              dst_release(&eth->dsa_meta[i]->dst);
+       }
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch b/queue-6.12/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
new file mode 100644 (file)
index 0000000..96c9fcb
--- /dev/null
@@ -0,0 +1,62 @@
+From 0574f4a70049763b884d46d77d931d637200c4a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 06:18:57 +0000
+Subject: net: fec: fix pinctrl default state restore order on resume
+
+From: Tapio Reijonen <tapio.reijonen@vaisala.com>
+
+[ Upstream commit b455410146bf723c7ebcb49ecd5becc0d6611482 ]
+
+In fec_resume(), fec_enet_clk_enable() is called before
+pinctrl_pm_select_default_state() in the non-WoL path, inverting the
+ordering used in fec_suspend() which correctly switches to the sleep
+pinctrl state before disabling clocks.
+
+For PHYs with the PHY_RST_AFTER_CLK_EN flag (e.g. TI DP83848 or
+SMSC LAN87xx), fec_enet_clk_enable() triggers a hardware reset pulse
+via the phy-reset GPIO. With the GPIO pin still in sleep pinctrl state
+at that point, the GPIO write has no physical effect and the PHY never
+receives the required reset after clock enable, leading to unreliable
+link establishment after system resume.
+
+Fix by restoring the default pinctrl state before enabling clocks,
+making resume the proper mirror of suspend. The call is made
+unconditionally: fec_suspend() only switches to the sleep pinctrl state
+on the non-WoL path and leaves the pins in the default state when WoL
+is enabled, so on a WoL resume the device is already in the default
+state and pinctrl_pm_select_default_state() is a no-op.
+
+Fixes: de40ed31b3c5 ("net: fec: add Wake-on-LAN support")
+Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20260529-b4-fec-resume-pinctrl-order-v3-1-6eda0f592fca@vaisala.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 9018a7d3864fd5..d8189c433847c4 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -4731,6 +4731,7 @@ static int fec_resume(struct device *dev)
+               if (fep->rpm_active)
+                       pm_runtime_force_resume(dev);
++              pinctrl_pm_select_default_state(&fep->pdev->dev);
+               ret = fec_enet_clk_enable(ndev, true);
+               if (ret) {
+                       rtnl_unlock();
+@@ -4747,8 +4748,6 @@ static int fec_resume(struct device *dev)
+                       val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
+                       writel(val, fep->hwp + FEC_ECNTRL);
+                       fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
+-              } else {
+-                      pinctrl_pm_select_default_state(&fep->pdev->dev);
+               }
+               fec_restart(ndev);
+               netif_tx_lock_bh(ndev);
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-6.12/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..2521ef9
--- /dev/null
@@ -0,0 +1,58 @@
+From 5a3e73af17de8592f11d1c29318e44c6ffb9ce24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index 27f0ab146026b4..d2dcdef85d39af 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -453,7 +453,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-6.12/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..dfddc33
--- /dev/null
@@ -0,0 +1,99 @@
+From 8c12d30aafec63c019661b8e91f899c5d6336801 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index b897d071fc4524..dff5767671b127 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -1212,6 +1212,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -1251,6 +1281,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       eth_hw_addr_set(netdev, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 2f0cab0c85e1d0..b8bb31c0400d16 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -181,6 +181,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-6.12/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..55f436a
--- /dev/null
@@ -0,0 +1,106 @@
+From 67cad93c67f9c335501764aec553b638e11ddfca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index d8103b2270d98f..539ea6693a2470 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -42,6 +42,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *user_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index eecad65fec92ca..7d903f0607439d 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -112,11 +112,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -129,7 +124,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void offload_action_hw_count_set(struct tc_action *act,
+-- 
+2.53.0
+
diff --git a/queue-6.12/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch b/queue-6.12/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
new file mode 100644 (file)
index 0000000..c577783
--- /dev/null
@@ -0,0 +1,228 @@
+From e2c97bfcb530099cb50b14133ab389b143429038 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 08:32:21 -0400
+Subject: net/sched: fix pedit partial COW leading to page cache corruption
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
+
+[ Upstream commit 899ee91156e57784090c5565e4f31bd7dbffbc5a ]
+
+tcf_pedit_act() computes the COW range for skb_ensure_writable()
+once before the key loop using tcfp_off_max_hint, but the hint does
+not account for the runtime header offset added by typed keys. This
+can leave part of the write region un-COW'd.
+
+Fix by moving skb_ensure_writable() inside the per-key loop where
+the actual write offset is known, and add overflow checking on the
+offset arithmetic. For negative offsets (e.g. Ethernet header edits
+at ingress), use skb_cow() to COW the headroom instead. Guard
+offset_valid() against INT_MIN, where negation is undefined.
+
+Fixes: 8b796475fd78 ("net/sched: act_pedit: really ensure the skb is writable")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Reported-by: Keenan Dong <keenanat2000@gmail.com>
+Reported-by: Han Guidong <2045gemini@gmail.com>
+Reported-by: Zhang Cen <rollkingzzc@gmail.com>
+Reviewed-by: Han Guidong <2045gemini@gmail.com>
+Tested-by: Han Guidong <2045gemini@gmail.com>
+Reviewed-by: Davide Caratti <dcaratti@redhat.com>
+Tested-by: Davide Caratti <dcaratti@redhat.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Tested-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260531123221.48732-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tc_act/tc_pedit.h |  1 -
+ net/sched/act_pedit.c         | 77 +++++++++++++++++++----------------
+ 2 files changed, 41 insertions(+), 37 deletions(-)
+
+diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
+index f58ee15cd858cf..cb7b82f2cbc7fd 100644
+--- a/include/net/tc_act/tc_pedit.h
++++ b/include/net/tc_act/tc_pedit.h
+@@ -15,7 +15,6 @@ struct tcf_pedit_parms {
+       struct tc_pedit_key     *tcfp_keys;
+       struct tcf_pedit_key_ex *tcfp_keys_ex;
+       int action;
+-      u32 tcfp_off_max_hint;
+       unsigned char tcfp_nkeys;
+       unsigned char tcfp_flags;
+       struct rcu_head rcu;
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index 4b65901397a888..c0a5f5d78dacd9 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -16,6 +16,8 @@
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+ #include <linux/slab.h>
++#include <linux/overflow.h>
++#include <linux/unaligned.h>
+ #include <net/ipv6.h>
+ #include <net/netlink.h>
+ #include <net/pkt_sched.h>
+@@ -242,7 +244,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+               goto out_free_ex;
+       }
+-      nparms->tcfp_off_max_hint = 0;
+       nparms->tcfp_flags = parm->flags;
+       nparms->tcfp_nkeys = parm->nkeys;
+@@ -268,14 +269,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+                                                  BITS_PER_TYPE(int) - 1,
+                                                  nparms->tcfp_keys[i].shift);
+-              /* The AT option can read a single byte, we can bound the actual
+-               * value with uchar max.
+-               */
+-              cur += (0xff & offmask) >> nparms->tcfp_keys[i].shift;
+-
+-              /* Each key touches 4 bytes starting from the computed offset */
+-              nparms->tcfp_off_max_hint =
+-                      max(nparms->tcfp_off_max_hint, cur + 4);
+       }
+       p = to_pedit(*a);
+@@ -318,15 +311,12 @@ static void tcf_pedit_cleanup(struct tc_action *a)
+               call_rcu(&parms->rcu, tcf_pedit_cleanup_rcu);
+ }
+-static bool offset_valid(struct sk_buff *skb, int offset)
++static bool offset_valid(struct sk_buff *skb, int offset, int len)
+ {
+-      if (offset > 0 && offset > skb->len)
+-              return false;
+-
+-      if  (offset < 0 && -offset > skb_headroom(skb))
++      if (offset < -(int)skb_headroom(skb))
+               return false;
+-      return true;
++      return offset <= (int)skb->len - len;
+ }
+ static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int header_type)
+@@ -393,18 +383,10 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+       struct tcf_pedit_key_ex *tkey_ex;
+       struct tcf_pedit_parms *parms;
+       struct tc_pedit_key *tkey;
+-      u32 max_offset;
+       int i;
+       parms = rcu_dereference_bh(p->parms);
+-      max_offset = (skb_transport_header_was_set(skb) ?
+-                    skb_transport_offset(skb) :
+-                    skb_network_offset(skb)) +
+-                   parms->tcfp_off_max_hint;
+-      if (skb_ensure_writable(skb, min(skb->len, max_offset)))
+-              goto done;
+-
+       tcf_lastuse_update(&p->tcf_tm);
+       tcf_action_update_bstats(&p->common, skb);
+@@ -412,10 +394,11 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+       tkey_ex = parms->tcfp_keys_ex;
+       for (i = parms->tcfp_nkeys; i > 0; i--, tkey++) {
++              int write_offset, write_len;
+               int offset = tkey->off;
+               int hoffset = 0;
+-              u32 *ptr, hdata;
+-              u32 val;
++              u32 cur_val, val;
++              u32 *ptr;
+               int rc;
+               if (tkey_ex) {
+@@ -433,13 +416,15 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+               if (tkey->offmask) {
+                       u8 *d, _d;
++                      int at_offset;
+-                      if (!offset_valid(skb, hoffset + tkey->at)) {
++                      if (check_add_overflow(hoffset, (int)tkey->at, &at_offset) ||
++                          !offset_valid(skb, at_offset, sizeof(_d))) {
+                               pr_info_ratelimited("tc action pedit 'at' offset %d out of bounds\n",
+                                                   hoffset + tkey->at);
+                               goto bad;
+                       }
+-                      d = skb_header_pointer(skb, hoffset + tkey->at,
++                      d = skb_header_pointer(skb, at_offset,
+                                              sizeof(_d), &_d);
+                       if (!d)
+                               goto bad;
+@@ -451,31 +436,51 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+                       }
+               }
+-              if (!offset_valid(skb, hoffset + offset)) {
+-                      pr_info_ratelimited("tc action pedit offset %d out of bounds\n", hoffset + offset);
++              if (check_add_overflow(hoffset, offset, &write_offset)) {
++                      pr_info_ratelimited("tc action pedit offset overflow\n");
+                       goto bad;
+               }
+-              ptr = skb_header_pointer(skb, hoffset + offset,
+-                                       sizeof(hdata), &hdata);
+-              if (!ptr)
++              if (!offset_valid(skb, write_offset, sizeof(*ptr))) {
++                      pr_info_ratelimited("tc action pedit offset %d out of bounds\n",
++                                          write_offset);
+                       goto bad;
++              }
++
++              if (write_offset < 0) {
++                      if (skb_cow(skb, -write_offset))
++                              goto bad;
++                      if (write_offset + (int)sizeof(*ptr) > 0) {
++                              if (skb_ensure_writable(skb,
++                                                      min_t(int, skb->len,
++                                                            write_offset + (int)sizeof(*ptr))))
++                                      goto bad;
++                      }
++              } else {
++                      if (check_add_overflow(write_offset, (int)sizeof(*ptr),
++                                             &write_len))
++                              goto bad;
++                      if (skb_ensure_writable(skb, min_t(int, skb->len,
++                                                         write_len)))
++                              goto bad;
++              }
++
++              ptr = (u32 *)(skb->data + write_offset);
++              cur_val = get_unaligned(ptr);
+               /* just do it, baby */
+               switch (cmd) {
+               case TCA_PEDIT_KEY_EX_CMD_SET:
+                       val = tkey->val;
+                       break;
+               case TCA_PEDIT_KEY_EX_CMD_ADD:
+-                      val = (*ptr + tkey->val) & ~tkey->mask;
++                      val = (cur_val + tkey->val) & ~tkey->mask;
+                       break;
+               default:
+                       pr_info_ratelimited("tc action pedit bad command (%d)\n", cmd);
+                       goto bad;
+               }
+-              *ptr = ((*ptr & tkey->mask) ^ val);
+-              if (ptr == &hdata)
+-                      skb_store_bits(skb, hoffset + offset, ptr, 4);
++              put_unaligned((cur_val & tkey->mask) ^ val, ptr);
+       }
+       goto done;
+-- 
+2.53.0
+
diff --git a/queue-6.12/net_sched-act_pedit-use-rcu-in-tcf_pedit_dump.patch b/queue-6.12/net_sched-act_pedit-use-rcu-in-tcf_pedit_dump.patch
new file mode 100644 (file)
index 0000000..ca654a6
--- /dev/null
@@ -0,0 +1,109 @@
+From 9f374bf663ac3cc81b8168bef435e6d5d61c5f15 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Jul 2025 09:02:01 +0000
+Subject: net_sched: act_pedit: use RCU in tcf_pedit_dump()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 9d096746572616a50cac4906f528a1959c0ee1c2 ]
+
+Also storing tcf_action into struct tcf_pedit_params
+makes sure there is no discrepancy in tcf_pedit_act().
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250709090204.797558-10-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 899ee91156e5 ("net/sched: fix pedit partial COW leading to page cache corruption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tc_act/tc_pedit.h |  1 +
+ net/sched/act_pedit.c         | 20 ++++++++++----------
+ 2 files changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
+index 83fe3993178180..f58ee15cd858cf 100644
+--- a/include/net/tc_act/tc_pedit.h
++++ b/include/net/tc_act/tc_pedit.h
+@@ -14,6 +14,7 @@ struct tcf_pedit_key_ex {
+ struct tcf_pedit_parms {
+       struct tc_pedit_key     *tcfp_keys;
+       struct tcf_pedit_key_ex *tcfp_keys_ex;
++      int action;
+       u32 tcfp_off_max_hint;
+       unsigned char tcfp_nkeys;
+       unsigned char tcfp_flags;
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index fc0a35a7b62ac7..4b65901397a888 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -279,7 +279,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+       }
+       p = to_pedit(*a);
+-
++      nparms->action = parm->action;
+       spin_lock_bh(&p->tcf_lock);
+       goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
+       oparms = rcu_replace_pointer(p->parms, nparms, 1);
+@@ -483,7 +483,7 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+ bad:
+       tcf_action_inc_overlimit_qstats(&p->common);
+ done:
+-      return p->tcf_action;
++      return parms->action;
+ }
+ static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u64 packets,
+@@ -500,19 +500,19 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
+                         int bind, int ref)
+ {
+       unsigned char *b = skb_tail_pointer(skb);
+-      struct tcf_pedit *p = to_pedit(a);
+-      struct tcf_pedit_parms *parms;
++      const struct tcf_pedit *p = to_pedit(a);
++      const struct tcf_pedit_parms *parms;
+       struct tc_pedit *opt;
+       struct tcf_t t;
+       int s;
+-      spin_lock_bh(&p->tcf_lock);
+-      parms = rcu_dereference_protected(p->parms, 1);
++      rcu_read_lock();
++      parms = rcu_dereference(p->parms);
+       s = struct_size(opt, keys, parms->tcfp_nkeys);
+       opt = kzalloc(s, GFP_ATOMIC);
+       if (unlikely(!opt)) {
+-              spin_unlock_bh(&p->tcf_lock);
++              rcu_read_unlock();
+               return -ENOBUFS;
+       }
+       opt->nkeys = parms->tcfp_nkeys;
+@@ -521,7 +521,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
+              flex_array_size(opt, keys, parms->tcfp_nkeys));
+       opt->index = p->tcf_index;
+       opt->flags = parms->tcfp_flags;
+-      opt->action = p->tcf_action;
++      opt->action = parms->action;
+       opt->refcnt = refcount_read(&p->tcf_refcnt) - ref;
+       opt->bindcnt = atomic_read(&p->tcf_bindcnt) - bind;
+@@ -540,13 +540,13 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
+       tcf_tm_dump(&t, &p->tcf_tm);
+       if (nla_put_64bit(skb, TCA_PEDIT_TM, sizeof(t), &t, TCA_PEDIT_PAD))
+               goto nla_put_failure;
+-      spin_unlock_bh(&p->tcf_lock);
++      rcu_read_unlock();
+       kfree(opt);
+       return skb->len;
+ nla_put_failure:
+-      spin_unlock_bh(&p->tcf_lock);
++      rcu_read_unlock();
+       nlmsg_trim(skb, b);
+       kfree(opt);
+       return -1;
+-- 
+2.53.0
+
diff --git a/queue-6.12/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-6.12/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..36583a9
--- /dev/null
@@ -0,0 +1,58 @@
+From 85d1d41c32d374b0878e8935ec4f231c6cc34992 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-6.12/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-6.12/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..8f5c33b
--- /dev/null
@@ -0,0 +1,50 @@
+From 28146e0ae0a82103c54c5971625108ba6cd31420 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index 5703846bea3b69..0f50ea92ced9df 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -208,7 +208,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -222,7 +222,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-6.12/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch b/queue-6.12/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
new file mode 100644 (file)
index 0000000..bedf2df
--- /dev/null
@@ -0,0 +1,96 @@
+From a590999c564903a3f5fbf7e41ecdad46049ade19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:09:19 +0800
+Subject: netfilter: nft_ct: bail out on template ct in get eval
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 3027ecbdb5fdf9200251c21d4818e4c447ef78e1 ]
+
+I noticed this issue while looking at a historic syzbot report [1].
+
+A rule like the one below is enough to trigger the bug:
+
+    table ip t {
+        chain pre {
+            type filter hook prerouting priority raw;
+            ct zone set 1
+            ct original saddr 1.2.3.4 accept
+        }
+    }
+
+The first expression attaches a per-cpu template ct via
+nft_ct_set_zone_eval() (nf_ct_tmpl_alloc -> kzalloc, tuple is all
+zero, nf_ct_l3num(ct) == 0). The next expression then calls
+nft_ct_get_eval() on the same skb, treats the template as a real ct
+and hits the 16-byte memcpy path. With dreg at NFT_REG32_15 this
+overflows past struct nft_regs on the kernel stack; with smaller
+dreg values it silently clobbers adjacent registers.
+
+Reject template ct at the eval entry and in nft_ct_get_fast_eval(),
+mirroring the check nft_ct_set_eval() already has. Additionally,
+bound the address copy in NFT_CT_SRC / NFT_CT_DST by priv->len
+instead of by nf_ct_l3num(ct): nf_ct_get_tuple() zeroes the tuple
+before pkt_to_tuple() fills in only the protocol-relevant leading
+bytes, so the trailing bytes of tuple->{src,dst}.u3.all are
+well-defined zero. priv->len is validated at rule load, so the
+copy size is now bounded by the destination register rather than
+by an untrusted field on the conntrack.
+
+[1]: https://syzkaller.appspot.com/bug?id=389cf09cb72926114fce90dc85a2c3231dcb647c
+
+Fixes: 45d9bcda21f4 ("netfilter: nf_tables: validate len in nft_validate_data_load()")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+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>
+---
+ net/netfilter/nft_ct.c      | 8 +++-----
+ net/netfilter/nft_ct_fast.c | 2 +-
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 5310c3dca8327b..65fbbf4a219e9e 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -78,7 +78,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (ct == NULL)
++      if (!ct || nf_ct_is_template(ct))
+               goto err;
+       switch (priv->key) {
+@@ -180,12 +180,10 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+       tuple = &ct->tuplehash[priv->dir].tuple;
+       switch (priv->key) {
+       case NFT_CT_SRC:
+-              memcpy(dest, tuple->src.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->src.u3.all, priv->len);
+               return;
+       case NFT_CT_DST:
+-              memcpy(dest, tuple->dst.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->dst.u3.all, priv->len);
+               return;
+       case NFT_CT_PROTO_SRC:
+               nft_reg_store16(dest, (__force u16)tuple->src.u.all);
+diff --git a/net/netfilter/nft_ct_fast.c b/net/netfilter/nft_ct_fast.c
+index e684c8a9184877..ecf7b3a404be26 100644
+--- a/net/netfilter/nft_ct_fast.c
++++ b/net/netfilter/nft_ct_fast.c
+@@ -30,7 +30,7 @@ void nft_ct_get_fast_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (!ct) {
++      if (!ct || nf_ct_is_template(ct)) {
+               regs->verdict.code = NFT_BREAK;
+               return;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.12/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-6.12/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..d0360a0
--- /dev/null
@@ -0,0 +1,113 @@
+From f438a624fd9fe9109adf28f5a293ca0c51abb9f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 6a851ac4dd048f..a277b2bd3275dc 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -21,6 +21,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -768,26 +770,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1192,27 +1199,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-6.12/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-6.12/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..bdf0529
--- /dev/null
@@ -0,0 +1,41 @@
+From 849c3cd18db9650f3371433888fef1ebaa6c70eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-6.12/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch b/queue-6.12/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch
new file mode 100644 (file)
index 0000000..72b414d
--- /dev/null
@@ -0,0 +1,44 @@
+From 37a8a8832baeff47353749b7cbe17fba5f6e2cce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 17:07:05 +0530
+Subject: octeontx2-af: Fix initialization of mcam's entry2target_pffunc field
+
+From: Suman Ghosh <sumang@marvell.com>
+
+[ Upstream commit 9a85ec3dc28b6df246801c19e4d9bae6297a25b0 ]
+
+NPC mcam entry stores a mapping between mcam entry and target pcifunc.
+During initialization of this field, API kmalloc_array has been used which
+caused some junk values to array. Whereas, the array is expected to be
+initialized by 0. This patch fixes the same by using kcalloc instead of
+kmalloc_array.
+
+Fixes: 55307fcb9258 ("octeontx2-af: Add mbox messages to install and delete MCAM rules")
+Signed-off-by: Suman Ghosh <sumang@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/1780054625-17090-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index e3038a912a5805..3e03f85bf362cb 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -1944,8 +1944,8 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
+               goto free_entry_cntr_map;
+       /* Alloc memory for saving target device of mcam rule */
+-      mcam->entry2target_pffunc = kmalloc_array(mcam->total_entries,
+-                                                sizeof(u16), GFP_KERNEL);
++      mcam->entry2target_pffunc = kcalloc(mcam->total_entries,
++                                          sizeof(u16), GFP_KERNEL);
+       if (!mcam->entry2target_pffunc)
+               goto free_cntr_refcnt;
+-- 
+2.53.0
+
diff --git a/queue-6.12/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch b/queue-6.12/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
new file mode 100644 (file)
index 0000000..95a4186
--- /dev/null
@@ -0,0 +1,119 @@
+From 582b42f16b56d31715b4137891d3f04d32233ea8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 10:28:53 +0530
+Subject: octeontx2-af: npc: Fix CPT channel mask in npc_install_flow
+
+From: Nithin Dabilpuram <ndabilpuram@marvell.com>
+
+[ Upstream commit 1d31eb27e570daa04f5373345f9ac98c95863be9 ]
+
+Use the CPT-aware NIX channel mask in the npc_install_flow path so that
+when the host PF installs steering rules in kernel for a VF used from
+userspace (e.g. DPDK), MCAM entries see the same channel mask semantics as
+other RX paths.
+
+Fixes: 56bcef528bd8 ("octeontx2-af: Use npc_install_flow API for promisc and broadcast entries")
+Cc: Naveen Mamindlapalli <naveenm@marvell.com>
+Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
+Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
+Link: https://patch.msgid.link/20260602045853.1558530-1-rkannoth@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |  1 +
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   | 32 +++++++++----------
+ .../marvell/octeontx2/af/rvu_npc_fs.c         |  2 +-
+ 3 files changed, 18 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index f94bf04788e986..77a03e29a77116 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -1020,6 +1020,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
+                       int slot);
+ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);
+ int rvu_cpt_init(struct rvu *rvu);
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu);
+ #define NDC_AF_BANK_MASK       GENMASK_ULL(7, 0)
+ #define NDC_AF_BANK_LINE_MASK  GENMASK_ULL(31, 16)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 3e03f85bf362cb..0163fbb758d3d3 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -597,6 +597,19 @@ void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
+                          NPC_AF_MCAMEX_BANKX_ACTION(index, bank), cfg);
+ }
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu)
++{
++      /* For cn10k the upper two bits of the channel number are
++       * cpt channel number. with masking out these bits in the
++       * mcam entry, same entry used for NIX will allow packets
++       * received from cpt for parsing.
++       */
++      if (!is_rvu_otx2(rvu))
++              return NIX_CHAN_CPT_X2P_MASK;
++      else
++              return 0xFFFu;
++}
++
+ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+                                int nixlf, u64 chan, u8 *mac_addr)
+ {
+@@ -640,7 +653,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+       eth_broadcast_addr((u8 *)&req.mask.dmac);
+       req.features = BIT_ULL(NPC_DMAC);
+       req.channel = chan;
+-      req.chan_mask = 0xFFFU;
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.intf = pfvf->nix_rx_intf;
+       req.op = action.op;
+       req.hdr.pcifunc = 0; /* AF is requester */
+@@ -710,11 +723,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+        * mcam entry, same entry used for NIX will allow packets
+        * received from cpt for parsing.
+        */
+-      if (!is_rvu_otx2(rvu)) {
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      } else {
+-              req.chan_mask = 0xFFFU;
+-      }
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       if (chan_cnt > 1) {
+               if (!is_power_of_2(chan_cnt)) {
+@@ -903,16 +912,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+       ether_addr_copy(req.mask.dmac, mac_addr);
+       req.features = BIT_ULL(NPC_DMAC);
+-      /* For cn10k the upper two bits of the channel number are
+-       * cpt channel number. with masking out these bits in the
+-       * mcam entry, same entry used for NIX will allow packets
+-       * received from cpt for parsing.
+-       */
+-      if (!is_rvu_otx2(rvu))
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      else
+-              req.chan_mask = 0xFFFU;
+-
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.channel = chan;
+       req.intf = pfvf->nix_rx_intf;
+       req.entry = index;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+index 0c484120be7993..73850213b1f30a 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+@@ -1484,7 +1484,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
+       /* ignore chan_mask in case pf func is not AF, revisit later */
+       if (!is_pffunc_af(req->hdr.pcifunc))
+-              req->chan_mask = 0xFFF;
++              req->chan_mask = rvu_get_cpt_chan_mask(rvu);
+       err = npc_check_unsupported_flows(rvu, req->features, req->intf);
+       if (err)
+-- 
+2.53.0
+
diff --git a/queue-6.12/octeontx2-pf-fix-ndc-sync-operation-errors.patch b/queue-6.12/octeontx2-pf-fix-ndc-sync-operation-errors.patch
new file mode 100644 (file)
index 0000000..9c40c4c
--- /dev/null
@@ -0,0 +1,40 @@
+From d9be109ef1df9d2231e0ce7868be817b95f8e00b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 17:07:57 +0530
+Subject: octeontx2-pf: Fix NDC sync operation errors
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit a910fb8f7b9e4c566db363e6c2ec378dc7153995 ]
+
+On system reboot "rvu_nicpf 0002:03:00.0: NDC sync operation failed"
+error messages are shown, even if the operations is successful.
+This is due to wrong if error check in ndc_syc() function.
+
+Fixes: 42c45ac1419c ("octeontx2-af: Sync NIX and NPA contexts from NDC to LLC/DRAM")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/1780054677-17249-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index 2de9c44ef57c77..ce01fab28624f2 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -3263,7 +3263,7 @@ static void otx2_ndc_sync(struct otx2_nic *pf)
+       req->nix_lf_rx_sync = 1;
+       req->npa_lf_sync = 1;
+-      if (!otx2_sync_mbox_msg(mbox))
++      if (otx2_sync_mbox_msg(mbox))
+               dev_err(pf->dev, "NDC sync operation failed\n");
+       mutex_unlock(&mbox->lock);
+-- 
+2.53.0
+
diff --git a/queue-6.12/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-6.12/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..2bc2ab3
--- /dev/null
@@ -0,0 +1,58 @@
+From 69b73d02df434ebe99b3e6599b31999a74a7fa7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 72db9f9e7beeae..81cb83caf62a15 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1403,8 +1403,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1412,9 +1414,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/ptp-vclock-switch-from-rcu-to-srcu.patch b/queue-6.12/ptp-vclock-switch-from-rcu-to-srcu.patch
new file mode 100644 (file)
index 0000000..a53f861
--- /dev/null
@@ -0,0 +1,85 @@
+From d39c3554013aefdb958c15e6cc6f384780e536cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:11:47 +0200
+Subject: ptp: vclock: Switch from RCU to SRCU
+
+From: Kurt Kanzenbach <kurt@linutronix.de>
+
+[ Upstream commit 672bd0519e27c357c43b7f8c0d653fce3817d06e ]
+
+The usage of PTP vClocks leads immediately to the following issues with
+ptp4l with LOCKDEP and DEBUG_ATOMIC_SLEEP enabled: "BUG: sleeping function
+called from invalid context".
+
+ptp_convert_timestamp() acquires a mutex_t within a RCU read section.  This
+is illegal, because acquiring a mutex_t can result in voluntary scheduling
+request which is not allowed within a RCU read section.
+
+Replace the RCU usage with SRCU where sleeping is allowed.
+
+Reported-by: Florian Zeitz <florian.zeitz@schettke.com>
+Closes: https://lore.kernel.org/all/00a8cce8-410e-4038-98af-49be6d93d7bd@schettke.com/
+Fixes: 67d93ffc0f3c ("ptp: vclock: use mutex to fix "sleep on atomic" bug")
+Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260529-vclock_rcu-v2-1-02a5531fab92@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_vclock.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
+index 8ed4b85989242f..5e2730c73bc286 100644
+--- a/drivers/ptp/ptp_vclock.c
++++ b/drivers/ptp/ptp_vclock.c
+@@ -19,6 +19,8 @@ static DEFINE_SPINLOCK(vclock_hash_lock);
+ static DEFINE_READ_MOSTLY_HASHTABLE(vclock_hash, 8);
++DEFINE_STATIC_SRCU(vclock_srcu);
++
+ static void ptp_vclock_hash_add(struct ptp_vclock *vclock)
+ {
+       spin_lock(&vclock_hash_lock);
+@@ -37,7 +39,7 @@ static void ptp_vclock_hash_del(struct ptp_vclock *vclock)
+       spin_unlock(&vclock_hash_lock);
+-      synchronize_rcu();
++      synchronize_srcu(&vclock_srcu);
+ }
+ static int ptp_vclock_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+@@ -276,14 +278,16 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+ {
+       unsigned int hash = vclock_index % HASH_SIZE(vclock_hash);
+       struct ptp_vclock *vclock;
+-      u64 ns;
+       u64 vclock_ns = 0;
++      int srcu_idx;
++      u64 ns;
+       ns = ktime_to_ns(*hwtstamp);
+-      rcu_read_lock();
++      srcu_idx = srcu_read_lock(&vclock_srcu);
+-      hlist_for_each_entry_rcu(vclock, &vclock_hash[hash], vclock_hash_node) {
++      hlist_for_each_entry_srcu(vclock, &vclock_hash[hash], vclock_hash_node,
++                                srcu_read_lock_held(&vclock_srcu)) {
+               if (vclock->clock->index != vclock_index)
+                       continue;
+@@ -294,7 +298,7 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+               break;
+       }
+-      rcu_read_unlock();
++      srcu_read_unlock(&vclock_srcu, srcu_idx);
+       return ns_to_ktime(vclock_ns);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-6.12/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..f001832
--- /dev/null
@@ -0,0 +1,87 @@
+From 72d983ff1c88faa4171275db30dd712b9c491e5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 376d4ce5ebb3cb..613c5c3fa8462e 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2598,11 +2598,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
index 10876eb5954fba22e4a32ebcdfb7a7afe827cac3..cc27fc4b65fabe7d3c5364075cb90d297812da6a 100644 (file)
@@ -6,3 +6,52 @@ arm-fix-hash_name-fault.patch
 arm-fix-branch-predictor-hardening.patch
 net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch
 wifi-remove-zero-length-arrays.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch
+erofs-add-sysfs-node-to-drop-internal-caches.patch
+erofs-tidy-up-synchronous-decompression.patch
+erofs-fix-use-after-free-on-sbi-sync_decompress.patch
+ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch
+devlink-release-nested-relation-on-devlink-free.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-annotate-sk-sk_write_space-for-udp-sockmap.patch
+hsr-remove-warn_once-in-hsr_addr_is_self.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
+bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
+bluetooth-bnep-reject-short-frames-before-parsing.patch
+bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
+bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch
+bluetooth-iso-fix-not-using-bc_sid-as-advertisement-.patch
+bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch
+bluetooth-mgmt-fix-backward-compatibility-with-users.patch
+octeontx2-pf-fix-ndc-sync-operation-errors.patch
+octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ptp-vclock-switch-from-rcu-to-srcu.patch
+net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
+net_sched-act_pedit-use-rcu-in-tcf_pedit_dump.patch
+net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
+octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
+vxlan-vnifilter-send-notification-on-vni-add.patch
+vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
+ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
diff --git a/queue-6.12/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch b/queue-6.12/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch
new file mode 100644 (file)
index 0000000..bf17e4f
--- /dev/null
@@ -0,0 +1,44 @@
+From b447174623e201ed0c1c00b326a060b483f73b5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 May 2026 19:22:18 +0530
+Subject: soc: qcom: ice: Return -ENODEV if the ICE platform device is not
+ found
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+
+[ Upstream commit 5a4dc805a80e6fe303d6a4748cd451ea15987ffd ]
+
+By the time the consumer driver calls devm_of_qcom_ice_get(), all the
+platform devices for ICE nodes would've been created by
+of_platform_default_populate().
+
+So for the absence of any platform device, -ENODEV should not returned, not
+-EPROBE_DEFER.
+
+Fixes: 2afbf43a4aec ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver")
+Tested-by: Sumit Garg <sumit.garg@oss.qualcomm.com> # OP-TEE as TZ
+Acked-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260518-qcom-ice-fix-v7-2-2a595382185b@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index 9d89bfc50e8b86..66b64509347a64 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -301,7 +301,7 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
+       pdev = of_find_device_by_node(node);
+       if (!pdev) {
+               dev_err(dev, "Cannot find device node %s\n", node->name);
+-              return ERR_PTR(-EPROBE_DEFER);
++              return ERR_PTR(-ENODEV);
+       }
+       ice = platform_get_drvdata(pdev);
+-- 
+2.53.0
+
diff --git a/queue-6.12/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-6.12/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..a65b3db
--- /dev/null
@@ -0,0 +1,287 @@
+From 524240f19e8109ccb8154a72935966ff4c7a2b58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index d0f397c9024201..2386bbd38ce78b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch b/queue-6.12/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
new file mode 100644 (file)
index 0000000..a1985a1
--- /dev/null
@@ -0,0 +1,55 @@
+From eb4ce7d7a563f721bbc55c3b39b93949546e6a49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:37 -0700
+Subject: vxlan: vnifilter: fix spurious notification on VNI update
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit 84683b5b60c7274e2c8f7f413d39d78d3db5540f ]
+
+When a VNI is re-added with the same attributes (e.g. same group or no
+group), vxlan_vni_update() sends a spurious RTM_NEWTUNNEL notification
+even though nothing changed.
+
+The bug is that 'if (changed)' tests whether the pointer is non-NULL,
+not the bool value it points to. Since every caller passes a valid
+pointer, the condition is always true and the notification fires
+unconditionally.
+
+Fix by dereferencing the pointer: 'if (*changed)'.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100
+ # bridge vni add vni 1000 dev vxlan100  # spurious notification
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-3-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index 1ab78a8bb9e011..272fa31ef07454 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -671,7 +671,7 @@ static int vxlan_vni_update(struct vxlan_dev *vxlan,
+       if (ret)
+               return ret;
+-      if (changed)
++      if (*changed)
+               vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.12/vxlan-vnifilter-send-notification-on-vni-add.patch b/queue-6.12/vxlan-vnifilter-send-notification-on-vni-add.patch
new file mode 100644 (file)
index 0000000..60b29c5
--- /dev/null
@@ -0,0 +1,69 @@
+From 9996fd4ada87cd72370682cf6999c1beb23274f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:36 -0700
+Subject: vxlan: vnifilter: send notification on VNI add
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit aa6ca1c5c338907817374b59f7551fd855a88754 ]
+
+When a new VNI is added to a vxlan device with vnifilter enabled,
+no RTM_NEWTUNNEL notification is sent to userspace. This means
+'bridge monitor vni' never shows VNI add events, even though
+VNI delete events are reported correctly.
+
+The bug is in vxlan_vni_add(), where the notification is guarded by
+'if (changed)'. The 'changed' flag is set by vxlan_vni_update_group()
+only when the multicast group or remote IP is modified, but for a
+new VNI added without a group (e.g. in L3 VxLAN interface scenarios),
+the function returns early without setting changed=true. Since this
+is a new VNI, the notification should be sent unconditionally.
+
+The notification is not guarded by the return value of
+vxlan_vni_update_group() because, at this point, the VNI has already
+been inserted into the hash table and list with no rollback on error.
+The VNI will be visible in 'bridge vni show' regardless, so userspace
+should be informed. This is consistent with vxlan_vni_del() which also
+notifies unconditionally.
+
+The 'if (changed)' guard remains correct in vxlan_vni_update(), which
+handles the case where a VNI already exists and is being re-added --
+there, we only want to notify if the group/remote actually changed.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100    # no notification
+ # bridge vni delete vni 1000 dev vxlan100 # notification received
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Reported-by: Chirag Shah <chirag@nvidia.com>
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-2-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index 06d19e90eadb59..1ab78a8bb9e011 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -769,8 +769,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+       err = vxlan_vni_update_group(vxlan, vninode, group, true, &changed,
+                                    extack);
+-      if (changed)
+-              vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
++      vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return err;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.12/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch b/queue-6.12/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch
new file mode 100644 (file)
index 0000000..31acf42
--- /dev/null
@@ -0,0 +1,61 @@
+From 6382fe010e4ca3ae5aa318f30c74ada1f0e8c584 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 06:47:21 +0530
+Subject: wifi: mac80211: limit injected antenna index in
+ ieee80211_parse_tx_radiotap
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 6c0cf89f36ac0c0fd8687a4ccdce2efb23a9c663 ]
+
+When parsing the radiotap header of an injected frame,
+ieee80211_parse_tx_radiotap() uses the IEEE80211_RADIOTAP_ANTENNA value
+directly as a shift count:
+
+       info->control.antennas |= BIT(*iterator.this_arg);
+
+*iterator.this_arg is an 8-bit value taken straight from the frame
+supplied by userspace, so BIT() can be asked to shift by up to 255. That
+is undefined behaviour on the unsigned long and is reported by UBSAN:
+
+  UBSAN: shift-out-of-bounds in net/mac80211/tx.c:2174:30
+  shift exponent 235 is too large for 64-bit type 'unsigned long'
+  Call Trace:
+   ieee80211_parse_tx_radiotap+0xadb/0x1950 net/mac80211/tx.c:2174
+   ieee80211_monitor_start_xmit+0xb1f/0x1250 net/mac80211/tx.c:2451
+   ...
+   packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3109
+
+info->control.antennas is a 2-bit bitmap (u8 antennas:2), so only antenna
+indices 0 and 1 can ever be represented. Ignore any larger value instead
+of shifting out of bounds.
+
+Reported-by: syzbot+8e0622f6d9446420271f@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8e0622f6d9446420271f
+Fixes: ef246a1480cc ("wifi: mac80211: support antenna control in injection")
+Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
+Link: https://patch.msgid.link/20260531011721.102941-1-kartikey406@gmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/tx.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 0458cbba232e21..b82c7884a92db3 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -2169,7 +2169,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
+               case IEEE80211_RADIOTAP_ANTENNA:
+                       /* this can appear multiple times, keep a bitmap */
+-                      info->control.antennas |= BIT(*iterator.this_arg);
++                      /* control.antennas is only a 2-bit bitmap */
++                      if (*iterator.this_arg < 2)
++                              info->control.antennas |= BIT(*iterator.this_arg);
+                       break;
+               case IEEE80211_RADIOTAP_DATA_RETRIES:
+-- 
+2.53.0
+
diff --git a/queue-6.18/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-6.18/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..a2ef324
--- /dev/null
@@ -0,0 +1,67 @@
+From 6be8b447edb1cf5f18babfe5ae6fe69f20e44524 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index e116d308a8df6d..37eaff3f7b6940 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-6.18/af_unix-fix-inq_len-update-problem-in-partial-read.patch b/queue-6.18/af_unix-fix-inq_len-update-problem-in-partial-read.patch
new file mode 100644 (file)
index 0000000..3bd5aec
--- /dev/null
@@ -0,0 +1,60 @@
+From 289519c54e407fb9c75630b620820d759f7bac9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 19:36:39 +0800
+Subject: af_unix: Fix inq_len update problem in partial read
+
+From: Jianyu Li <jianyu.li@mediatek.com>
+
+[ Upstream commit c1f07a7f2d47aeb9878301e7bb36bc1c2bc2be8e ]
+
+Currently inq_len is updated only when the whole skb is consumed.
+If only part of the data is read, following SIOCINQ query would
+get value greater than what actually left.
+
+This change update inq_len timely in unix_stream_read_generic(),
+and adjust unix_stream_read_skb() accordingly to prevent
+repetitive update.
+
+Fixes: f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().")
+Signed-off-by: Jianyu Li <jianyu.li@mediatek.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260601113640.231897-2-jianyu.li@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index faf04d1b6c013c..b339f83caf036e 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2891,7 +2891,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
+               return -EAGAIN;
+       }
+-      WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
++      WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb));
+ #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
+       if (skb == u->oob_skb) {
+@@ -3065,11 +3065,12 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
+                               unix_detach_fds(&scm, skb);
+                       }
+-                      if (unix_skb_len(skb))
+-                              break;
+-
+                       spin_lock(&sk->sk_receive_queue.lock);
+-                      WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
++                      WRITE_ONCE(u->inq_len, u->inq_len - chunk);
++                      if (unix_skb_len(skb)) {
++                              spin_unlock(&sk->sk_receive_queue.lock);
++                              break;
++                      }
+                       __skb_unlink(skb, &sk->sk_receive_queue);
+                       spin_unlock(&sk->sk_receive_queue.lock);
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch b/queue-6.18/arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch
new file mode 100644 (file)
index 0000000..f2ef95b
--- /dev/null
@@ -0,0 +1,56 @@
+From ba748aca4bd9f4a5ab450a8cd4057518ce9ef09c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Mar 2026 09:53:29 +0200
+Subject: ARM: dts: microchip: sam9x7: fix GMAC clock configuration
+
+From: Mihai Sain <mihai.sain@microchip.com>
+
+[ Upstream commit 765aaba18413a66f6c8fe8416336ca9b3dd98a79 ]
+
+The GMAC node incorrectly listed four clocks, including a separate tx_clk
+and a TSU GCK clock sourced from ID 67. According to the SAM9X7 clocking
+scheme, the GMAC uses only three clocks: HCLK, PCLK, and the TSU GCK
+derived from the GMAC peripheral clock (ID 24).
+
+Remove the unused tx_clk, update the clock-names accordingly, and correct
+the assigned clock to use GCK 24 instead of GCK 67. This aligns the device
+tree with the actual hardware clock topology and prevents misconfiguration
+of the GMAC clock tree.
+
+[root@SAM9X75 ~]$ cat /sys/kernel/debug/clk/clk_summary | grep gmac
+
+gmac_gclk      1       1        1        266666666   0          0     50000      Y         f802c000.ethernet           tsu_clk
+                                                                                           f802c000.ethernet           tsu_clk
+gmac_clk       2       2        0        266666666   0          0     50000      Y         f802c000.ethernet           hclk
+                                                                                           f802c000.ethernet           pclk
+
+Fixes: 41af45af8bc3 ("ARM: dts: at91: sam9x7: add device tree for SoC")
+Signed-off-by: Mihai Sain <mihai.sain@microchip.com>
+Link: https://lore.kernel.org/r/20260309075329.1528-5-mihai.sain@microchip.com
+[claudiu.beznea: massaged the patch description]
+Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/microchip/sam9x7.dtsi | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/boot/dts/microchip/sam9x7.dtsi b/arch/arm/boot/dts/microchip/sam9x7.dtsi
+index d242d7a934d0fa..c680a5033b6b4e 100644
+--- a/arch/arm/boot/dts/microchip/sam9x7.dtsi
++++ b/arch/arm/boot/dts/microchip/sam9x7.dtsi
+@@ -990,9 +990,9 @@ gmac: ethernet@f802c000 {
+                                    <62 IRQ_TYPE_LEVEL_HIGH 3>,        /* Queue 3 */
+                                    <63 IRQ_TYPE_LEVEL_HIGH 3>,        /* Queue 4 */
+                                    <64 IRQ_TYPE_LEVEL_HIGH 3>;        /* Queue 5 */
+-                      clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>, <&pmc PMC_TYPE_GCK 67>;
+-                      clock-names = "hclk", "pclk", "tx_clk", "tsu_clk";
+-                      assigned-clocks = <&pmc PMC_TYPE_GCK 67>;
++                      clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>;
++                      clock-names = "hclk", "pclk", "tsu_clk";
++                      assigned-clocks = <&pmc PMC_TYPE_GCK 24>;
+                       assigned-clock-rates = <266666666>;
+                       status = "disabled";
+               };
+-- 
+2.53.0
+
diff --git a/queue-6.18/arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch b/queue-6.18/arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch
new file mode 100644 (file)
index 0000000..e77f709
--- /dev/null
@@ -0,0 +1,53 @@
+From bb6f4ebba7d67e9365cc1c19421838b8535a4ae5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Mar 2026 21:53:37 -0300
+Subject: arm64: dts: qcom: x1-dell-thena: remove i2c20 (battery SMBus) and
+ reserve its pins
+
+From: Val Packett <val@packett.cool>
+
+[ Upstream commit 4b15b03166cc5d28e9912287b1f9b6607c8710ec ]
+
+i2c20 is used by the battmgr service on the ADSP to communicate with the
+SBS interface of the battery. Initializing it from Linux would break the
+battmgr functionality when booted in EL2. Mark those pins as reserved.
+
+Fixes: e7733b42111c ("arm64: dts: qcom: Add support for Dell Inspiron 7441 / Latitude 7455")
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
+Signed-off-by: Val Packett <val@packett.cool>
+Link: https://lore.kernel.org/r/20260312005731.12488-2-val@packett.cool
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+index 847b678f040c00..5b5a10a31a253a 100644
+--- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+@@ -982,12 +982,6 @@ &i2c8 {
+       status = "okay";
+ };
+-&i2c20 {
+-      clock-frequency = <400000>;
+-
+-      status = "okay";
+-};
+-
+ &lpass_tlmm {
+       spkr_01_sd_n_active: spkr-01-sd-n-active-state {
+               pins = "gpio12";
+@@ -1306,6 +1300,7 @@ right_tweeter: speaker@0,1 {
+ &tlmm {
+       gpio-reserved-ranges = <44 4>,  /* SPI11 (TPM) */
+                              <76 4>,  /* SPI19 (TZ Protected) */
++                             <80 2>,  /* I2C20 (Battery SMBus) */
+                              <238 1>; /* UFS Reset */
+       cam_rgb_default: cam-rgb-default-state {
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch b/queue-6.18/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
new file mode 100644 (file)
index 0000000..8fa80cd
--- /dev/null
@@ -0,0 +1,71 @@
+From 679966cc98c19bd833847bd527dd55aef6f2a20c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 17:39:53 +0800
+Subject: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame()
+ extension handling
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+[ Upstream commit 72b8deccff17a7644e0367e1aaf1a36cfb014324 ]
+
+In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
+BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:
+
+1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
+   performs a native-endian read. The BNEP protocol specifies this field
+   in big-endian (network byte order), and the same file correctly uses
+   get_unaligned_be16() for the identical fields in
+   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().
+
+2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
+   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
+   entry), the filter extension length field already represents the total
+   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
+   which reads the same field as a byte count and divides by 4 to get
+   the number of filter entries.
+
+   The bogus * 2 means skb_pull advances twice as far as it should,
+   either dropping valid data from the next header or causing the pull
+   to fail entirely when the doubled length exceeds the remaining skb.
+
+Fix by splitting the pull into two steps: first use skb_pull_data() to
+safely pull and validate the 3-byte fixed header (ctrl type + length),
+then pull the variable-length data using the properly decoded length.
+
+Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index b3cef7a4db5412..0de5df690bd0b2 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+                               goto badframe;
+                       break;
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET:
+-                      /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+-                      if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
++              case BNEP_FILTER_NET_TYPE_SET: {
++                      u8 *hdr;
++
++                      /* Pull ctrl type (1 b) + len (2 b) */
++                      hdr = skb_pull_data(skb, 3);
++                      if (!hdr)
++                              goto badframe;
++                      /* Pull data (len bytes); length is big-endian */
++                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+                               goto badframe;
+                       break;
++              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-bnep-reject-short-frames-before-parsing.patch b/queue-6.18/bluetooth-bnep-reject-short-frames-before-parsing.patch
new file mode 100644 (file)
index 0000000..a964aec
--- /dev/null
@@ -0,0 +1,170 @@
+From ef7e5bc527e344f789ad03691086bf793d6eab80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 11:22:09 +0800
+Subject: Bluetooth: bnep: reject short frames before parsing
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 6770d3a8acdf9151769180cc3710346c4cfbe6f0 ]
+
+A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
+packet type byte immediately and, for control packets, reads the control
+opcode and setup UUID-size byte before proving that those bytes are
+present. bnep_rx_control() also dereferences the control opcode without
+rejecting an empty control payload.
+
+Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
+return gates each dereference. Split the control handler so the frame
+path can pass an opcode that has already been pulled, and keep the
+byte-buffer wrapper for extension control payloads.
+
+For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
+setup payload. struct bnep_setup_conn_req carries destination and source
+service UUIDs after that byte, each uuid_size bytes, so the parser now
+documents that tuple explicitly instead of leaving the pull length as an
+opaque multiplication.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
+The buggy address belongs to the object at ffff88800c0f7908 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 1-byte
+region [ffff88800c0f7908, ffff88800c0f7909)
+Read of size 1
+Call trace:
+  dump_stack_lvl+0xb3/0x140 (?:?)
+  print_address_description+0x57/0x3a0 (?:?)
+  bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
+  print_report+0xb9/0x2b0 (?:?)
+  __virt_addr_valid+0x1ba/0x3a0 (?:?)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  kasan_addr_to_slab+0x21/0x60 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
+  worker_thread+0x65c/0xe40 (?:?)
+  __kthread_parkme+0x184/0x230 (?:?)
+  kthread+0x35e/0x470 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  ret_from_fork+0x586/0x870 (?:?)
+  __switch_to+0x74f/0xdc0 (?:?)
+  ret_from_fork_asm+0x1a/0x30 (?:?)
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index 0de5df690bd0b2..5c5f53ff30e8e5 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
+       return 0;
+ }
+-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
++                             int len)
+ {
+-      u8  cmd = *(u8 *)data;
+       int err = 0;
+-      data++;
+-      len--;
+-
+       switch (cmd) {
+       case BNEP_CMD_NOT_UNDERSTOOD:
+       case BNEP_SETUP_CONN_RSP:
+@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+       return err;
+ }
++static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++{
++      if (len < 1)
++              return -EILSEQ;
++
++      return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
++}
++
+ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct bnep_ext_hdr *h;
+@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct net_device *dev = s->dev;
+       struct sk_buff *nskb;
++      u8 *data;
+       u8 type, ctrl_type;
+       dev->stats.rx_bytes += skb->len;
+-      type = *(u8 *) skb->data;
+-      skb_pull(skb, 1);
+-      ctrl_type = *(u8 *)skb->data;
++      data = skb_pull_data(skb, sizeof(type));
++      if (!data)
++              goto badframe;
++      type = *data;
+       if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
+               goto badframe;
+       if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
+-              if (bnep_rx_control(s, skb->data, skb->len) < 0) {
++              data = skb_pull_data(skb, sizeof(ctrl_type));
++              if (!data)
++                      goto badframe;
++              ctrl_type = *data;
++
++              if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
+                       dev->stats.tx_errors++;
+                       kfree_skb(skb);
+                       return 0;
+@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+               /* Verify and pull ctrl message since it's already processed */
+               switch (ctrl_type) {
+-              case BNEP_SETUP_CONN_REQ:
+-                      /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+-                      if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
++              case BNEP_SETUP_CONN_REQ: {
++                      u8 uuid_size;
++
++                      /* Pull uuid_size and the dst/src service UUIDs. */
++                      data = skb_pull_data(skb, sizeof(uuid_size));
++                      if (!data)
++                              goto badframe;
++                      uuid_size = *data;
++                      if (!skb_pull(skb, uuid_size + uuid_size))
+                               goto badframe;
+                       break;
++              }
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET: {
+-                      u8 *hdr;
+-
+-                      /* Pull ctrl type (1 b) + len (2 b) */
+-                      hdr = skb_pull_data(skb, 3);
+-                      if (!hdr)
++              case BNEP_FILTER_NET_TYPE_SET:
++                      /* Pull: len (2 b), data (len bytes) */
++                      data = skb_pull_data(skb, sizeof(u16));
++                      if (!data)
+                               goto badframe;
+-                      /* Pull data (len bytes); length is big-endian */
+-                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
++                      if (!skb_pull(skb, get_unaligned_be16(data)))
+                               goto badframe;
+                       break;
+-              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch b/queue-6.18/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
new file mode 100644 (file)
index 0000000..4da1c51
--- /dev/null
@@ -0,0 +1,58 @@
+From a0c4e2eec04bb3ca408aa2aff7d619ce4a19607f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 08:54:26 +0530
+Subject: Bluetooth: fix memory leak in error path of hci_alloc_dev()
+
+From: Bharath Reddy <kbreddy.rpbc@gmail.com>
+
+[ Upstream commit 37b3009bf5976e8ab77c8b9a9bc3bbd7ff49e37f ]
+
+Early failures in Bluetooth HCI UART configuration leak SRCU percpu
+memory.
+
+When device initialization fails before hci_register_dev() completes,
+the HCI_UNREGISTER flag is never set. As a result, when the device
+reference count reaches zero, bt_host_release() evaluates this flag as
+false and falls back to a direct kfree(hdev).
+
+Because hci_release_dev() is bypassed, the SRCU struct initialized
+early in hci_alloc_dev() is never cleaned up, resulting in a leak of
+percpu memory.
+
+Fix the leak by explicitly calling cleanup_srcu_struct() in the
+fallback (unregistered) branch of bt_host_release() before freeing
+the device.
+
+Reported-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=535ecc844591e50588a5
+Tested-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Fixes: 1d6123102e9f ("Bluetooth: hci_core: Fix use-after-free in vhci_flush()")
+Signed-off-by: Bharath Reddy <kbreddy.rpbc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sysfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
+index 041ce9adc378ae..8957ce7c21b76c 100644
+--- a/net/bluetooth/hci_sysfs.c
++++ b/net/bluetooth/hci_sysfs.c
+@@ -83,10 +83,12 @@ static void bt_host_release(struct device *dev)
+ {
+       struct hci_dev *hdev = to_hci_dev(dev);
+-      if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
++      if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_release_dev(hdev);
+-      else
++      } else {
++              cleanup_srcu_struct(&hdev->srcu);
+               kfree(hdev);
++      }
+       module_put(THIS_MODULE);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch b/queue-6.18/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch
new file mode 100644 (file)
index 0000000..38f7cc6
--- /dev/null
@@ -0,0 +1,157 @@
+From f633d9bbb4434b66d7516b1dc4123908de67839b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 20:19:07 +0900
+Subject: Bluetooth: ISO: Fix data-race on iso_pi fields in hci_get_route calls
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 9ca7053d6215d89c33f28893bfd1625a32919d3f ]
+
+iso_connect_bis(), iso_connect_cis(), iso_listen_bis(), and
+iso_conn_big_sync() call hci_get_route() using iso_pi(sk)->dst,
+iso_pi(sk)->src, and iso_pi(sk)->src_type without holding lock_sock().
+
+These fields may be modified concurrently by connect() or setsockopt()
+on the same socket, resulting in data-races reported by KCSAN.
+
+Fix this by snapshotting the required fields under lock_sock() before
+calling hci_get_route().
+
+BUG: KCSAN: data-race in memcmp+0x45/0xb0
+
+race at unknown origin, with read to 0xffff8880122135cf of 1 bytes
+by task 333 on cpu 1:
+ memcmp+0x45/0xb0
+ hci_get_route+0x27e/0x490
+ iso_connect_cis+0x4c/0xa10
+ iso_sock_connect+0x60e/0xb30
+ __sys_connect_file+0xbd/0xe0
+ __sys_connect+0xe0/0x110
+ __x64_sys_connect+0x40/0x50
+ x64_sys_call+0xcad/0x1c60
+ do_syscall_64+0x133/0x590
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 241f51931c35 ("Bluetooth: ISO: Avoid circular locking dependency")
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 60 +++++++++++++++++++++++++++++++++------------
+ 1 file changed, 44 insertions(+), 16 deletions(-)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 355487613c82a0..c1e3015a6630d5 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -336,12 +336,20 @@ static int iso_connect_bis(struct sock *sk)
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      u8 src_type, bc_sid;
+       int err;
+-      BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      bc_sid = iso_pi(sk)->bc_sid;
++      release_sock(sk);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      BT_DBG("%pMR (SID 0x%2.2x)", &src, bc_sid);
++
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -433,12 +441,19 @@ static int iso_connect_cis(struct sock *sk)
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      u8 src_type;
+       int err;
+-      BT_DBG("%pMR -> %pMR", &iso_pi(sk)->src, &iso_pi(sk)->dst);
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      release_sock(sk);
++
++      BT_DBG("%pMR -> %pMR", &src, &dst);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -1138,18 +1153,25 @@ static int iso_sock_connect(struct socket *sock, struct sockaddr *addr,
+ static int iso_listen_bis(struct sock *sk)
+ {
+-      struct hci_dev *hdev;
+-      int err = 0;
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
++      struct hci_dev *hdev;
++      bdaddr_t src, dst;
++      u8 src_type, bc_sid;
++      int err = 0;
++
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      bc_sid = iso_pi(sk)->bc_sid;
++      release_sock(sk);
+-      BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
+-             &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
++      BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &src, &dst, bc_sid);
+       write_lock(&iso_sk_list.lock);
+-      if (__iso_get_sock_listen_by_sid(&iso_pi(sk)->src, &iso_pi(sk)->dst,
+-                                       iso_pi(sk)->bc_sid))
++      if (__iso_get_sock_listen_by_sid(&src, &dst, bc_sid))
+               err = -EADDRINUSE;
+       write_unlock(&iso_sk_list.lock);
+@@ -1157,8 +1179,7 @@ static int iso_listen_bis(struct sock *sk)
+       if (err)
+               return err;
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -1494,9 +1515,16 @@ static void iso_conn_big_sync(struct sock *sk)
+ {
+       int err;
+       struct hci_dev *hdev;
++      bdaddr_t src, dst;
++      u8 src_type;
++
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      release_sock(sk);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return;
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch b/queue-6.18/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch
new file mode 100644 (file)
index 0000000..9fa0b35
--- /dev/null
@@ -0,0 +1,36 @@
+From 3b8b08499b44e9ded90f5623bc11214eede0b337 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 14:45:42 -0400
+Subject: Bluetooth: ISO: Fix not releasing hdev reference on iso_conn_big_sync
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 5cbf290b79351971f20c7a533247e8d58a3f970c ]
+
+hci_get_route() returns a reference-counted hci_dev pointer via
+hci_dev_hold(). The function exits normally or with an error without ever
+releasing it.
+
+Fixes: 07a9342b94a9 ("Bluetooth: ISO: Send BIG Create Sync via hci_sync")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 9b421e4a2466f7..355487613c82a0 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1521,6 +1521,7 @@ static void iso_conn_big_sync(struct sock *sk)
+       release_sock(sk);
+       hci_dev_unlock(hdev);
++      hci_dev_put(hdev);
+ }
+ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-mgmt-fix-backward-compatibility-with-users.patch b/queue-6.18/bluetooth-mgmt-fix-backward-compatibility-with-users.patch
new file mode 100644 (file)
index 0000000..8ad8d53
--- /dev/null
@@ -0,0 +1,43 @@
+From 5c267a5c381b0de5a4f5e6b4df829e9d61d2571f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:48:34 -0400
+Subject: Bluetooth: MGMT: Fix backward compatibility with userspace
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 149324fc762c2a7acef9c26790566f81f475e51f ]
+
+bluetoothd has a bug with makes it send extra bytes as part of
+MGMT_OP_ADD_EXT_ADV_DATA which are now being checked to be the
+exact the expected length, relax this so only when the expected
+length is greater than the data length to cause an error since
+that would result in accessing invalid memory, otherwise just
+ignore the extra bytes.
+
+Link: https://lore.kernel.org/linux-bluetooth/20260602204749.210857-1-luiz.dentz@gmail.com/T/#u
+Fixes: d3f7d17960ed ("Bluetooth: MGMT: validate Add Extended Advertising Data length")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 9bb82d1fdc3cad..c87ec0138c430b 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -9098,8 +9098,9 @@ static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data,
+       BT_DBG("%s", hdev->name);
+-      expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len);
+-      if (expected_len != data_len)
++      expected_len = struct_size(cp, data, cp->adv_data_len +
++                                 cp->scan_rsp_len);
++      if (expected_len > data_len)
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
+                                      MGMT_STATUS_INVALID_PARAMS);
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-6.18/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..0a36592
--- /dev/null
@@ -0,0 +1,73 @@
+From 02eb89cb047559a5667489fb7d7b5b741d27d40b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 91d1c0d132f9e1..9bb82d1fdc3cad 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -8622,6 +8622,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -8638,12 +8644,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-6.18/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..f43662d
--- /dev/null
@@ -0,0 +1,126 @@
+From 6baf3c8af14a9be825a91d4720c42ec01f85f432 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index 3052436e9c6de5..2286efef62f5b6 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -940,6 +950,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -953,6 +964,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -980,9 +996,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       release_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch b/queue-6.18/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
new file mode 100644 (file)
index 0000000..473d92d
--- /dev/null
@@ -0,0 +1,167 @@
+From ba692464bb091ebb574316ec4b9be5503d96c037 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:04:43 +0900
+Subject: Bluetooth: RFCOMM: validate skb length in MCC handlers
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 23882b828c3c8c51d0c946446a396b10abb3b16b ]
+
+The RFCOMM MCC handlers cast skb->data to protocol-specific structs
+without validating skb->len first. A malicious remote device can send
+truncated MCC frames and trigger out-of-bounds reads in these handlers.
+
+Fix this by using skb_pull_data() to validate and access the required
+data before dereferencing it.
+
+rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
+1-byte RPN requests. Handle this by validating only the DLCI byte first,
+and validating the full struct only when len > 1.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
+ 1 file changed, 49 insertions(+), 18 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
+index 96250807b32b44..dfade1933fa730 100644
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -1431,10 +1431,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
+ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_pn *pn = (void *) skb->data;
++      struct rfcomm_pn *pn;
+       struct rfcomm_dlc *d;
+-      u8 dlci = pn->dlci;
++      u8 dlci;
++
++      pn = skb_pull_data(skb, sizeof(*pn));
++      if (!pn)
++              return -EILSEQ;
++      dlci = pn->dlci;
+       BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
+       if (!dlci)
+@@ -1483,8 +1488,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
+ {
+-      struct rfcomm_rpn *rpn = (void *) skb->data;
+-      u8 dlci = __get_dlci(rpn->dlci);
++      struct rfcomm_rpn *rpn;
++      u8 dlci;
+       u8 bit_rate  = 0;
+       u8 data_bits = 0;
+@@ -1495,15 +1500,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+       u8 xoff_char = 0;
+       u16 rpn_mask = RFCOMM_RPN_PM_ALL;
+-      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+-              dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+-              rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++      if (len == 1) {
++              rpn = skb_pull_data(skb, 1);
++              if (!rpn)
++                      return -EILSEQ;
+-      if (!cr)
+-              return 0;
++              dlci = __get_dlci(rpn->dlci);
++
++              if (!cr)
++                      return 0;
+-      if (len == 1) {
+-              /* This is a request, return default (according to ETSI TS 07.10) settings */
+               bit_rate  = RFCOMM_RPN_BR_9600;
+               data_bits = RFCOMM_RPN_DATA_8;
+               stop_bits = RFCOMM_RPN_STOP_1;
+@@ -1514,6 +1520,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+               goto rpn_out;
+       }
++      rpn = skb_pull_data(skb, sizeof(*rpn));
++      if (!rpn)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rpn->dlci);
++
++      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
++             dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
++             rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++
++      if (!cr)
++              return 0;
++
+       /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+        * no parity, no flow control lines, normal XON/XOFF chars */
+@@ -1589,9 +1608,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_rls *rls = (void *) skb->data;
+-      u8 dlci = __get_dlci(rls->dlci);
++      struct rfcomm_rls *rls;
++      u8 dlci;
++      rls = skb_pull_data(skb, sizeof(*rls));
++      if (!rls)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rls->dlci);
+       BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+       if (!cr)
+@@ -1608,10 +1632,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_msc *msc = (void *) skb->data;
++      struct rfcomm_msc *msc;
+       struct rfcomm_dlc *d;
+-      u8 dlci = __get_dlci(msc->dlci);
++      u8 dlci;
++
++      msc = skb_pull_data(skb, sizeof(*msc));
++      if (!msc)
++              return -EILSEQ;
++      dlci = __get_dlci(msc->dlci);
+       BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
+       d = rfcomm_dlc_get(s, dlci);
+@@ -1644,17 +1673,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
+ {
+-      struct rfcomm_mcc *mcc = (void *) skb->data;
++      struct rfcomm_mcc *mcc;
+       u8 type, cr, len;
++      mcc = skb_pull_data(skb, sizeof(*mcc));
++      if (!mcc)
++              return -EILSEQ;
++
+       cr   = __test_cr(mcc->type);
+       type = __get_mcc_type(mcc->type);
+       len  = __get_mcc_len(mcc->len);
+       BT_DBG("%p type 0x%x cr %d", s, type, cr);
+-      skb_pull(skb, 2);
+-
+       switch (type) {
+       case RFCOMM_PN:
+               rfcomm_recv_pn(s, cr, skb);
+-- 
+2.53.0
+
diff --git a/queue-6.18/bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch b/queue-6.18/bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch
new file mode 100644 (file)
index 0000000..e0259ec
--- /dev/null
@@ -0,0 +1,96 @@
+From f1f36984a93c743e274e14081bc73b82756c2b99 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 20:19:08 +0900
+Subject: Bluetooth: SCO: Fix data-race on sco_pi fields in sco_connect
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 4847c5bca22227100ae69e96af86618b6fd2671f ]
+
+sco_sock_connect() copies the destination address into sco_pi(sk)->dst
+under lock_sock(), then releases the lock and calls sco_connect(),
+which reads dst, src, setting, and codec without holding lock_sock() in
+hci_get_route() and hci_connect_sco().
+
+These fields may be modified concurrently by connect(), bind(), or
+setsockopt() on the same socket, resulting in data-races reported by
+KCSAN.
+
+Fix this by snapshotting dst, src, setting, and codec under lock_sock()
+at the start of sco_connect() before passing them to hci_get_route()
+and hci_connect_sco().
+
+BUG: KCSAN: data-race in memcmp+0x45/0xb0
+
+race at unknown origin, with read to 0xffff88800e6b0dd0 of 1 bytes
+by task 315 on cpu 0:
+ memcmp+0x45/0xb0
+ hci_connect_acl+0x1b7/0x6b0
+ hci_connect_sco+0x4d/0xb30
+ sco_sock_connect+0x27b/0xd60
+ __sys_connect_file+0xbd/0xe0
+ __sys_connect+0xe0/0x110
+ __x64_sys_connect+0x40/0x50
+ x64_sys_call+0xcad/0x1c60
+ do_syscall_64+0x133/0x590
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 9a8ec9e8ebb5 ("Bluetooth: SCO: Fix possible circular locking dependency on sco_connect_cfm")
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/sco.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index a536c2edd14f24..a19ae1b39bc02f 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -312,11 +312,21 @@ static int sco_connect(struct sock *sk)
+       struct sco_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      struct bt_codec codec;
++      __u16 setting;
+       int err, type;
+-      BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
++      lock_sock(sk);
++      bacpy(&src, &sco_pi(sk)->src);
++      bacpy(&dst, &sco_pi(sk)->dst);
++      setting = sco_pi(sk)->setting;
++      codec = sco_pi(sk)->codec;
++      release_sock(sk);
++
++      BT_DBG("%pMR -> %pMR", &src, &dst);
+-      hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
++      hdev = hci_get_route(&dst, &src, BDADDR_BREDR);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -327,7 +337,7 @@ static int sco_connect(struct sock *sk)
+       else
+               type = SCO_LINK;
+-      switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
++      switch (setting & SCO_AIRMODE_MASK) {
+       case SCO_AIRMODE_TRANSP:
+               if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
+                       err = -EOPNOTSUPP;
+@@ -336,8 +346,8 @@ static int sco_connect(struct sock *sk)
+               break;
+       }
+-      hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
+-                             sco_pi(sk)->setting, &sco_pi(sk)->codec,
++      hcon = hci_connect_sco(hdev, type, &dst,
++                             setting, &codec,
+                              READ_ONCE(sk->sk_sndtimeo));
+       if (IS_ERR(hcon)) {
+               err = PTR_ERR(hcon);
+-- 
+2.53.0
+
diff --git a/queue-6.18/devlink-release-nested-relation-on-devlink-free.patch b/queue-6.18/devlink-release-nested-relation-on-devlink-free.patch
new file mode 100644 (file)
index 0000000..bc58449
--- /dev/null
@@ -0,0 +1,49 @@
+From f691b230f1b949237fe5b72ed56660e22bcb6b22 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 22:14:10 +0300
+Subject: devlink: Release nested relation on devlink free
+
+From: Mark Bloch <mbloch@nvidia.com>
+
+[ Upstream commit 3522b21fd7e1863d0734537737bd59f1b90d0190 ]
+
+devlink relation state is normally released from devl_unregister(), which
+calls devlink_rel_put(). This misses devlink instances that get a nested
+relation before registration and then fail probe before devl_register() is
+reached.
+
+That flow can happen for SFs. The child devlink gets linked to its
+parent before registration, then a later probe error calls devlink_free()
+directly. Since the instance was never registered, devl_unregister() is not
+called and devlink->rel is leaked.
+
+Release any pending relation from devlink_free() as well. The registered
+path is unchanged because devl_unregister() already clears devlink->rel
+before devlink_free() runs.
+
+Fixes: c137743bce02 ("devlink: introduce object and nested devlink relationship infra")
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://patch.msgid.link/20260528191411.3270532-1-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/devlink/core.c b/net/devlink/core.c
+index 58093f49c0905e..d8f875b229897e 100644
+--- a/net/devlink/core.c
++++ b/net/devlink/core.c
+@@ -469,6 +469,8 @@ void devlink_free(struct devlink *devlink)
+ {
+       ASSERT_DEVLINK_NOT_REGISTERED(devlink);
++      devlink_rel_put(devlink);
++
+       WARN_ON(!list_empty(&devlink->trap_policer_list));
+       WARN_ON(!list_empty(&devlink->trap_group_list));
+       WARN_ON(!list_empty(&devlink->trap_list));
+-- 
+2.53.0
+
diff --git a/queue-6.18/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-6.18/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..1ee8f3f
--- /dev/null
@@ -0,0 +1,71 @@
+From 5e1ccdc5946bfc7bc022f05c375409ef75d172d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index 76a35cce85028e..7f661e8cbcc2be 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1590,18 +1590,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-6.18/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-6.18/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..c0798f9
--- /dev/null
@@ -0,0 +1,53 @@
+From eec73918e4335f223a891decdb8b0956e0b649d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index 32c3f46b21daea..5c7f8d952ec1a1 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -166,6 +166,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-6.18/erofs-fix-use-after-free-on-sbi-sync_decompress.patch b/queue-6.18/erofs-fix-use-after-free-on-sbi-sync_decompress.patch
new file mode 100644 (file)
index 0000000..2756e77
--- /dev/null
@@ -0,0 +1,66 @@
+From fd4dfabe3a247973a71218f972ea62d5e09a43e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:27:16 +0800
+Subject: erofs: fix use-after-free on sbi->sync_decompress
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+[ Upstream commit 1aee05e814d292064bf5fa15733741040cdc48ba ]
+
+z_erofs_decompress_kickoff() can race with filesystem unmount, causing
+a use-after-free on sbi->sync_decompress.
+
+When I/O completes, z_erofs_endio() calls z_erofs_decompress_kickoff()
+to queue z_erofs_decompressqueue_work() asynchronously. Then, after all
+folios are unlocked, unmount workflow can proceed and sbi will be freed
+before accessing to sbi->sync_decompress.
+
+Thread (unmount)        I/O completion        kworker
+                        queue_work
+                                              z_erofs_decompressqueue_work
+                                               (all folios are unlocked)
+cleanup_mnt
+ ..
+ erofs_kill_sb
+  erofs_sb_free
+   kfree(sbi)
+                        access sbi->sync_decompress  // UAF!!
+
+Fixes: 40452ffca3c1 ("erofs: add sysfs node to control sync decompression strategy")
+Reported-by: syzbot+52bae5c495dbe261a0bc@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=52bae5c495dbe261a0bc
+Reviewed-by: Chao Yu <chao@kernel.org>
+Reviewed-by: Jianan Huang <jnhuang95@gmail.com>
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/erofs/zdata.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index e98d9cb4fe99a4..a02ce7c06f9e1e 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -1443,6 +1443,9 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+       if (atomic_add_return(bios, &io->pending_bios))
+               return;
+       if (z_erofs_in_atomic()) {
++              /* See `sync_decompress` in sysfs-fs-erofs for more details */
++              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
++                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+ #ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
+               struct kthread_worker *worker;
+@@ -1459,9 +1462,6 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+ #else
+               queue_work(z_erofs_workqueue, &io->u.work);
+ #endif
+-              /* See `sync_decompress` in sysfs-fs-erofs for more details */
+-              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
+-                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+               return;
+       }
+       gfp_flag = memalloc_noio_save();
+-- 
+2.53.0
+
diff --git a/queue-6.18/erofs-tidy-up-synchronous-decompression.patch b/queue-6.18/erofs-tidy-up-synchronous-decompression.patch
new file mode 100644 (file)
index 0000000..5add32b
--- /dev/null
@@ -0,0 +1,193 @@
+From fed83c9497a73f9eb5e4b3b61defb2fb1ded7df5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jan 2026 11:43:30 +0800
+Subject: erofs: tidy up synchronous decompression
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+[ Upstream commit cc831ab33644088c1eef78936de24701014d520a ]
+
+ - Get rid of `sbi->opt.max_sync_decompress_pages` since it's fixed as
+   3 all the time;
+
+ - Add Z_EROFS_MAX_SYNC_DECOMPRESS_BYTES in bytes instead of in pages,
+   since for non-4K pages, 3-page limitation makes no sense;
+
+ - Move `sync_decompress` to sbi to avoid unexpected remount impact;
+
+ - Fold z_erofs_is_sync_decompress() into its caller;
+
+ - Better description of sysfs entry `sync_decompress`.
+
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Stable-dep-of: 1aee05e814d2 ("erofs: fix use-after-free on sbi->sync_decompress")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/ABI/testing/sysfs-fs-erofs | 14 ++++++----
+ fs/erofs/internal.h                      |  5 +---
+ fs/erofs/super.c                         |  3 +-
+ fs/erofs/sysfs.c                         |  2 +-
+ fs/erofs/zdata.c                         | 35 +++++++++---------------
+ 5 files changed, 25 insertions(+), 34 deletions(-)
+
+diff --git a/Documentation/ABI/testing/sysfs-fs-erofs b/Documentation/ABI/testing/sysfs-fs-erofs
+index 76d9808ed58143..b9243c7f28d718 100644
+--- a/Documentation/ABI/testing/sysfs-fs-erofs
++++ b/Documentation/ABI/testing/sysfs-fs-erofs
+@@ -10,12 +10,16 @@ Description:       Shows all enabled kernel features.
+ What:         /sys/fs/erofs/<disk>/sync_decompress
+ Date:         November 2021
+ Contact:      "Huang Jianan" <huangjianan@oppo.com>
+-Description:  Control strategy of sync decompression:
++Description:  Control strategy of synchronous decompression. Synchronous
++              decompression tries to decompress in the reader thread for
++              synchronous reads and small asynchronous reads (<= 12 KiB):
+-              - 0 (default, auto): enable for readpage, and enable for
+-                readahead on atomic contexts only.
+-              - 1 (force on): enable for readpage and readahead.
+-              - 2 (force off): disable for all situations.
++              - 0 (auto, default): apply to synchronous reads only, but will
++                                   switch to 1 (force on) if any decompression
++                                   request is detected in atomic contexts;
++              - 1 (force on): apply to synchronous reads and small
++                              asynchronous reads;
++              - 2 (force off): disable synchronous decompression completely.
+ What:         /sys/fs/erofs/<disk>/drop_caches
+ Date:         November 2024
+diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
+index f7f622836198da..87edbb4366d16c 100644
+--- a/fs/erofs/internal.h
++++ b/fs/erofs/internal.h
+@@ -59,10 +59,6 @@ enum {
+ struct erofs_mount_opts {
+       /* current strategy of how to use managed cache */
+       unsigned char cache_strategy;
+-      /* strategy of sync decompression (0 - auto, 1 - force on, 2 - force off) */
+-      unsigned int sync_decompress;
+-      /* threshold for decompression synchronously */
+-      unsigned int max_sync_decompress_pages;
+       unsigned int mount_opt;
+ };
+@@ -116,6 +112,7 @@ struct erofs_sb_info {
+       /* managed XArray arranged in physical block number */
+       struct xarray managed_pslots;
++      unsigned int sync_decompress;   /* strategy for sync decompression */
+       unsigned int shrinker_run_no;
+       u16 available_compr_algs;
+diff --git a/fs/erofs/super.c b/fs/erofs/super.c
+index f5f5d19459eccd..e6725e9847bedd 100644
+--- a/fs/erofs/super.c
++++ b/fs/erofs/super.c
+@@ -379,8 +379,7 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
+ {
+ #ifdef CONFIG_EROFS_FS_ZIP
+       sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
+-      sbi->opt.max_sync_decompress_pages = 3;
+-      sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
++      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
+ #endif
+ #ifdef CONFIG_EROFS_FS_XATTR
+       set_opt(&sbi->opt, XATTR_USER);
+diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
+index 1e0658a1d95b9a..86b22b9f0c1910 100644
+--- a/fs/erofs/sysfs.c
++++ b/fs/erofs/sysfs.c
+@@ -59,7 +59,7 @@ static struct erofs_attr erofs_attr_##_name = {                      \
+ #define ATTR_LIST(name) (&erofs_attr_##name.attr)
+ #ifdef CONFIG_EROFS_FS_ZIP
+-EROFS_ATTR_RW_UI(sync_decompress, erofs_mount_opts);
++EROFS_ATTR_RW_UI(sync_decompress, erofs_sb_info);
+ EROFS_ATTR_FUNC(drop_caches, 0200);
+ #endif
+ #ifdef CONFIG_EROFS_FS_ZIP_ACCEL
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index 33932d56d3a46e..e98d9cb4fe99a4 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -9,6 +9,7 @@
+ #include <linux/cpuhotplug.h>
+ #include <trace/events/erofs.h>
++#define Z_EROFS_MAX_SYNC_DECOMPRESS_BYTES     12288
+ #define Z_EROFS_PCLUSTER_MAX_PAGES    (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE)
+ #define Z_EROFS_INLINE_BVECS          2
+@@ -1097,21 +1098,6 @@ static int z_erofs_scan_folio(struct z_erofs_frontend *f,
+       return err;
+ }
+-static bool z_erofs_is_sync_decompress(struct erofs_sb_info *sbi,
+-                                     unsigned int readahead_pages)
+-{
+-      /* auto: enable for read_folio, disable for readahead */
+-      if ((sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO) &&
+-          !readahead_pages)
+-              return true;
+-
+-      if ((sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_FORCE_ON) &&
+-          (readahead_pages <= sbi->opt.max_sync_decompress_pages))
+-              return true;
+-
+-      return false;
+-}
+-
+ static bool z_erofs_page_is_invalidated(struct page *page)
+ {
+       return !page_folio(page)->mapping && !z_erofs_is_shortlived_page(page);
+@@ -1473,9 +1459,9 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+ #else
+               queue_work(z_erofs_workqueue, &io->u.work);
+ #endif
+-              /* enable sync decompression for readahead */
+-              if (sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
+-                      sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
++              /* See `sync_decompress` in sysfs-fs-erofs for more details */
++              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
++                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+               return;
+       }
+       gfp_flag = memalloc_noio_save();
+@@ -1795,16 +1781,21 @@ static void z_erofs_submit_queue(struct z_erofs_frontend *f,
+       z_erofs_decompress_kickoff(q[JQ_SUBMIT], nr_bios);
+ }
+-static int z_erofs_runqueue(struct z_erofs_frontend *f, unsigned int rapages)
++static int z_erofs_runqueue(struct z_erofs_frontend *f, unsigned int rabytes)
+ {
+       struct z_erofs_decompressqueue io[NR_JOBQUEUES];
+       struct erofs_sb_info *sbi = EROFS_I_SB(f->inode);
+-      bool force_fg = z_erofs_is_sync_decompress(sbi, rapages);
++      int syncmode = sbi->sync_decompress;
++      bool force_fg;
+       int err;
++      force_fg = (syncmode == EROFS_SYNC_DECOMPRESS_AUTO && !rabytes) ||
++              (syncmode == EROFS_SYNC_DECOMPRESS_FORCE_ON &&
++                      (rabytes <= Z_EROFS_MAX_SYNC_DECOMPRESS_BYTES));
++
+       if (f->head == Z_EROFS_PCLUSTER_TAIL)
+               return 0;
+-      z_erofs_submit_queue(f, io, &force_fg, !!rapages);
++      z_erofs_submit_queue(f, io, &force_fg, !!rabytes);
+       /* handle bypass queue (no i/o pclusters) immediately */
+       err = z_erofs_decompress_queue(&io[JQ_BYPASS], &f->pagepool);
+@@ -1925,7 +1916,7 @@ static void z_erofs_readahead(struct readahead_control *rac)
+       z_erofs_pcluster_readmore(&f, rac, false);
+       z_erofs_pcluster_end(&f);
+-      (void)z_erofs_runqueue(&f, nrpages);
++      (void)z_erofs_runqueue(&f, nrpages << PAGE_SHIFT);
+       erofs_put_metabuf(&f.map.buf);
+       erofs_release_pages(&f.pagepool);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/hsr-remove-warn_once-in-hsr_addr_is_self.patch b/queue-6.18/hsr-remove-warn_once-in-hsr_addr_is_self.patch
new file mode 100644 (file)
index 0000000..6e31a29
--- /dev/null
@@ -0,0 +1,109 @@
+From b80a12a83986dc841b7f4e2429aecfc20d25afe4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 May 2026 06:42:58 +0000
+Subject: hsr: Remove WARN_ONCE() in hsr_addr_is_self().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit afd0f17ca46258cec3a5cc48b8df9327fe772490 ]
+
+syzbot reported the warning [0] in hsr_addr_is_self(),
+whose assumption is simply wrong.
+
+hsr->self_node is cleared in hsr_del_self_node(), which
+is called from hsr_dellink().
+
+Since dev->rtnl_link_ops->dellink() is called before
+unregister_netdevice_many(), there is a window when
+user can find the device but without hsr->self_node.
+
+Let's remove WARN_ONCE() in hsr_addr_is_self().
+
+[0]:
+HSR: No self node
+WARNING: net/hsr/hsr_framereg.c:39 at hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39, CPU#0: syz.4.16848/17220
+Modules linked in:
+CPU: 0 UID: 0 PID: 17220 Comm: syz.4.16848 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39
+Code: 33 2f 41 0f b7 dd 89 ee 09 de 31 ff e8 c8 b4 c6 f6 09 dd 74 54 e8 0f b0 c6 f6 31 ed eb 53 e8 06 b0 c6 f6 48 8d 3d 2f 50 9c 04 <67> 48 0f b9 3a 31 ed eb 42 e8 c1 13 1f 00 89 c5 31 ff 89 c6 e8 96
+RSP: 0018:ffffc900041c70e0 EFLAGS: 00010283
+RAX: ffffffff8afdc6ca RBX: ffffffff8afdc4e6 RCX: 0000000000080000
+RDX: ffffc90010493000 RSI: 0000000000000948 RDI: ffffffff8f9a1700
+RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
+R10: ffffc900041c71e8 R11: fffff52000838e3f R12: dffffc0000000000
+R13: ffff888041f9e3c0 R14: ffff888086ee3802 R15: 0000000000000000
+FS:  00007f6fe985d6c0(0000) GS:ffff888126176000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f80bd437dac CR3: 0000000025096000 CR4: 00000000003526f0
+DR0: ffffffffffffffff DR1: 00000000000001f8 DR2: 0000000000000002
+DR3: ffffffffefffff15 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ check_local_dest net/hsr/hsr_forward.c:592 [inline]
+ fill_frame_info net/hsr/hsr_forward.c:728 [inline]
+ hsr_forward_skb+0xa11/0x2a80 net/hsr/hsr_forward.c:739
+ hsr_dev_xmit+0x253/0x370 net/hsr/hsr_device.c:236
+ __netdev_start_xmit include/linux/netdevice.h:5368 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5377 [inline]
+ xmit_one net/core/dev.c:3888 [inline]
+ dev_hard_start_xmit+0x2df/0x860 net/core/dev.c:3904
+ __dev_queue_xmit+0x1428/0x3900 net/core/dev.c:4870
+ neigh_output include/net/neighbour.h:556 [inline]
+ ip_finish_output2+0xcec/0x10b0 net/ipv4/ip_output.c:237
+ ip_send_skb net/ipv4/ip_output.c:1510 [inline]
+ ip_push_pending_frames+0x8b/0x110 net/ipv4/ip_output.c:1530
+ raw_sendmsg+0x1547/0x1a50 net/ipv4/raw.c:659
+ sock_sendmsg_nosec net/socket.c:787 [inline]
+ __sock_sendmsg net/socket.c:802 [inline]
+ ____sys_sendmsg+0x7da/0x9c0 net/socket.c:2698
+ ___sys_sendmsg+0x2a5/0x360 net/socket.c:2752
+ __sys_sendmsg net/socket.c:2784 [inline]
+ __do_sys_sendmsg net/socket.c:2789 [inline]
+ __se_sys_sendmsg net/socket.c:2787 [inline]
+ __x64_sys_sendmsg+0x1c3/0x2a0 net/socket.c:2787
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f6feb62ce59
+Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f6fe985d028 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f6feb8a6090 RCX: 00007f6feb62ce59
+RDX: 0000000000000000 RSI: 0000200000000000 RDI: 0000000000000004
+RBP: 00007f6feb6c2d6f R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007f6feb8a6128 R14: 00007f6feb8a6090 R15: 00007ffcf01cc488
+ </TASK>
+
+Fixes: f266a683a480 ("net/hsr: Better frame dispatch")
+Reported-by: syzbot+652670cf249077eb498b@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1a861e.b111c304.35cd64.0016.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260530064300.340793-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_framereg.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index 3a2a2fa7a0a396..bd2fbbc4420b29 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -52,10 +52,8 @@ bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr)
+       rcu_read_lock();
+       sn = rcu_dereference(hsr->self_node);
+-      if (!sn) {
+-              WARN_ONCE(1, "HSR: No self node\n");
++      if (!sn)
+               goto out;
+-      }
+       if (ether_addr_equal(addr, sn->macaddress_A) ||
+           ether_addr_equal(addr, sn->macaddress_B))
+-- 
+2.53.0
+
diff --git a/queue-6.18/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-6.18/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..d74677c
--- /dev/null
@@ -0,0 +1,56 @@
+From 4169245357913fbe03ee6115885a9ddfbf58e02c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-6.18/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-6.18/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..6bf3954
--- /dev/null
@@ -0,0 +1,54 @@
+From eb5e7143752fc3268890e252c814783c5f1f6b28 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index be8815ce3ac242..09d745112c1526 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -530,6 +530,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch b/queue-6.18/ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch
new file mode 100644 (file)
index 0000000..dde3c60
--- /dev/null
@@ -0,0 +1,124 @@
+From 3f1cabfb96610f6b061e5abbcf6d300097ac742e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:22:18 +0800
+Subject: ipv6: anycast: insert aca into global hash under idev->lock
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit f723ccaff2fb72b71ae8a9fd283f0dee4d9ae7a3 ]
+
+syzbot reported a splat [1]: a slab-use-after-free in
+ipv6_chk_acast_addr(), which walks the global inet6_acaddr_lst[] hash
+under RCU and dereferences a struct ifacaddr6 that has already been
+freed while still linked in the hash, so a later reader walks into a
+dangling node.
+
+In __ipv6_dev_ac_inc() the aca is allocated with refcount 1, then
+aca_get() bumps it to 2 to keep it alive across the unlocked region.
+It is published to idev->ac_list under idev->lock, but
+ipv6_add_acaddr_hash() runs after write_unlock_bh(). A concurrent
+teardown (ipv6_ac_destroy_dev() from addrconf_ifdown(), under RTNL)
+can slip into that window:
+
+  CPU0 __ipv6_dev_ac_inc           CPU1 ipv6_ac_destroy_dev (RTNL)
+  ------------------------------   ------------------------------------
+  aca_alloc()              refcnt 1
+  aca_get()               refcnt 2
+  write_lock_bh(idev->lock)
+    add aca to ac_list
+  write_unlock_bh(idev->lock)
+                                   write_lock_bh(idev->lock)
+                                     pull aca off ac_list
+                                   write_unlock_bh(idev->lock)
+                                   ipv6_del_acaddr_hash(aca)
+                                     hlist_del_init_rcu() is a no-op,
+                                     aca is not in the hash yet
+                                   aca_put()           refcnt 2->1
+  ipv6_add_acaddr_hash(aca)
+    aca now inserted into the hash
+  aca_put()                refcnt 1->0
+    call_rcu(aca_free_rcu) -> kfree(aca)
+
+The hash removal becomes a no-op because the insertion has not
+happened yet, so once CPU0 inserts and drops the last reference, the
+aca is freed while still linked in inet6_acaddr_lst[], and readers
+dereference freed memory after the slab slot is reused.
+
+This window opened once RTNL stopped serializing the join path against
+device teardown. Move ipv6_add_acaddr_hash() inside the idev->lock
+section so the ac_list and hash insertions are atomic with respect to
+teardown: a racing remover now either misses the aca entirely or finds
+it in both lists.
+
+acaddr_hash_lock is now nested under idev->lock, which is acquired in
+softirq context, so switch all acaddr_hash_lock sites to spin_lock_bh()
+to avoid the irq lock inversion reported in [2].
+
+[1] https://syzkaller.appspot.com/bug?extid=a01df04303c131efbf3a
+[2] https://lore.kernel.org/netdev/6a194ef7.ba3b1513.1890b4.0000.GAE@google.com/
+
+Reported-by: syzbot+819eb928d120d2bdad0e@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a191f87.ce022c6e.138e56.0003.GAE@google.com/T/
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Fixes: eb1ac9ff6c4a ("ipv6: anycast: Don't hold RTNL for IPV6_JOIN_ANYCAST.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260529152219.235475-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/anycast.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
+index 52599584422bf4..819c4ff10997e0 100644
+--- a/net/ipv6/anycast.c
++++ b/net/ipv6/anycast.c
+@@ -243,16 +243,16 @@ static void ipv6_add_acaddr_hash(struct net *net, struct ifacaddr6 *aca)
+ {
+       unsigned int hash = inet6_acaddr_hash(net, &aca->aca_addr);
+-      spin_lock(&acaddr_hash_lock);
++      spin_lock_bh(&acaddr_hash_lock);
+       hlist_add_head_rcu(&aca->aca_addr_lst, &inet6_acaddr_lst[hash]);
+-      spin_unlock(&acaddr_hash_lock);
++      spin_unlock_bh(&acaddr_hash_lock);
+ }
+ static void ipv6_del_acaddr_hash(struct ifacaddr6 *aca)
+ {
+-      spin_lock(&acaddr_hash_lock);
++      spin_lock_bh(&acaddr_hash_lock);
+       hlist_del_init_rcu(&aca->aca_addr_lst);
+-      spin_unlock(&acaddr_hash_lock);
++      spin_unlock_bh(&acaddr_hash_lock);
+ }
+ static void aca_get(struct ifacaddr6 *aca)
+@@ -371,10 +371,10 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
+       aca->aca_next = idev->ac_list;
+       rcu_assign_pointer(idev->ac_list, aca);
+-      write_unlock_bh(&idev->lock);
+-
+       ipv6_add_acaddr_hash(net, aca);
++      write_unlock_bh(&idev->lock);
++
+       ip6_ins_rt(net, f6i);
+       addrconf_join_solict(idev->dev, &aca->aca_addr);
+@@ -649,8 +649,8 @@ void ipv6_anycast_cleanup(void)
+ {
+       int i;
+-      spin_lock(&acaddr_hash_lock);
++      spin_lock_bh(&acaddr_hash_lock);
+       for (i = 0; i < IN6_ADDR_HSIZE; i++)
+               WARN_ON(!hlist_empty(&inet6_acaddr_lst[i]));
+-      spin_unlock(&acaddr_hash_lock);
++      spin_unlock_bh(&acaddr_hash_lock);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch b/queue-6.18/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
new file mode 100644 (file)
index 0000000..f39b33b
--- /dev/null
@@ -0,0 +1,107 @@
+From 5a688c86061ed594756a1c02aa894a2400dbad73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 13:18:11 +0300
+Subject: ipv6: mcast: Fix use-after-free when processing MLD queries
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ]
+
+When processing an MLD query, a pointer to the multicast group address
+is retrieved when initially parsing the packet. This pointer is later
+dereferenced without being reloaded despite the fact that the skb header
+might have been reallocated following the pskb_may_pull() calls, leading
+to a use-after-free [1].
+
+Fix by copying the multicast group address when the packet is initially
+parsed.
+
+[1]
+BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512)
+Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
+
+Workqueue: mld mld_query_work
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+print_address_description.constprop.0 (mm/kasan/report.c:378)
+print_report (mm/kasan/report.c:482)
+kasan_report (mm/kasan/report.c:595)
+__mld_query_work (net/ipv6/mcast.c:1512)
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+</TASK>
+
+[...]
+
+Freed by task 118:
+kasan_save_stack (mm/kasan/common.c:57)
+kasan_save_track (mm/kasan/common.c:78)
+kasan_save_free_info (mm/kasan/generic.c:584)
+__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
+kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566)
+pskb_expand_head (net/core/skbuff.c:2335)
+__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4))
+__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+
+Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Reviewed-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/mcast.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index 016b572e7d6f02..f4b3cb48387096 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1424,9 +1424,9 @@ void igmp6_event_query(struct sk_buff *skb)
+ static void __mld_query_work(struct sk_buff *skb)
+ {
+       struct mld2_query *mlh2 = NULL;
+-      const struct in6_addr *group;
+       unsigned long max_delay;
+       struct inet6_dev *idev;
++      struct in6_addr group;
+       struct ifmcaddr6 *ma;
+       struct mld_msg *mld;
+       int group_type;
+@@ -1458,8 +1458,8 @@ static void __mld_query_work(struct sk_buff *skb)
+               goto kfree_skb;
+       mld = (struct mld_msg *)icmp6_hdr(skb);
+-      group = &mld->mld_mca;
+-      group_type = ipv6_addr_type(group);
++      group = mld->mld_mca;
++      group_type = ipv6_addr_type(&group);
+       if (group_type != IPV6_ADDR_ANY &&
+           !(group_type&IPV6_ADDR_MULTICAST))
+@@ -1509,7 +1509,7 @@ static void __mld_query_work(struct sk_buff *skb)
+               }
+       } else {
+               for_each_mc_mclock(idev, ma) {
+-                      if (!ipv6_addr_equal(group, &ma->mca_addr))
++                      if (!ipv6_addr_equal(&group, &ma->mca_addr))
+                               continue;
+                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                               /* gsquery <- gsquery && mark */
+-- 
+2.53.0
+
diff --git a/queue-6.18/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-6.18/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..3490408
--- /dev/null
@@ -0,0 +1,127 @@
+From 1a4a0cfecbb4a611d48a7618da527ae721ef2bb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 29a36709e7f35c..2163f32ef6abc1 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1519,8 +1519,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index e442ba6033d5f8..a3b509908b8c0e 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1497,7 +1497,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1559,9 +1559,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1569,6 +1568,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1625,7 +1628,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index d4903723be7e90..49b2e5d2b2c837 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch b/queue-6.18/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
new file mode 100644 (file)
index 0000000..13b86bf
--- /dev/null
@@ -0,0 +1,75 @@
+From cca951b3bfc41f7b7032138e0b2f069f30d21bb2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 00:00:00 +0000
+Subject: ksmbd: fix NULL-deref of opinfo->conn in oplock/lease break notifiers
+
+From: Gil Portnoy <dddhkts1@gmail.com>
+
+[ Upstream commit b003086d76968298f22e7cf62239833b5a3a06b1 ]
+
+smb2_oplock_break_noti() and smb2_lease_break_noti() read opinfo->conn
+into a local with neither READ_ONCE() nor a NULL check.  Both run from
+oplock_break() after opinfo_get_list() has dropped ci->m_lock, so a
+concurrent SMB2 LOGOFF (session_fd_check()) can set op->conn = NULL
+under ci->m_lock within that window.  ksmbd_conn_r_count_inc(conn) then
+writes through NULL at offset 0xc4 -- a remotely triggerable oops.
+
+Guard both reads the way compare_guid_key() already does: read
+opinfo->conn with READ_ONCE() and return early if it is NULL, before
+allocating the work struct so nothing leaks.  A NULL conn means the
+client is gone and the break is moot, so return 0; oplock_break() treats
+that as success and runs the normal teardown.
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Assisted-by: Henry (Claude):claude-opus-4
+Signed-off-by: Gil Portnoy <dddhkts1@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/oplock.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index a84c01bceb8ba2..6454c7a4baa450 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -714,11 +714,16 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
+  */
+ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct oplock_break_info *br_info;
+       int ret = 0;
+-      struct ksmbd_work *work = ksmbd_alloc_work_struct();
++      struct ksmbd_work *work;
++
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++      work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+@@ -818,11 +823,15 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
+  */
+ static int smb2_lease_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct ksmbd_work *work;
+       struct lease_break_info *br_info;
+       struct lease *lease = opinfo->o_lease;
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++
+       work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+-- 
+2.53.0
+
diff --git a/queue-6.18/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch b/queue-6.18/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch
new file mode 100644 (file)
index 0000000..3e642c3
--- /dev/null
@@ -0,0 +1,176 @@
+From bfb18f410d820b124deadb9917b1ceb858fd2310 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:36:29 +0000
+Subject: l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit a213a8950414c684999dcf03edeea6c46ede172e ]
+
+pppol2tp_ioctl() read sock->sk->sk_user_data directly without any
+locks or reference counting.  If a controllable sleep was induced during
+copy_from_user() (e.g. via a userfaultfd page fault sleep), a concurrent
+socket close could trigger pppol2tp_session_close() asynchronously.  This
+frees the l2tp_session structure via the l2tp_session_del_work workqueue.
+Upon resuming, the ioctl thread dereferences the stale session pointer,
+resulting in a Use-After-Free (UAF).
+
+Fix this by securely fetching the session reference using the RCU-safe,
+refcounted helper pppol2tp_sock_to_session(sk) on entry.  This locks the
+session's refcount across the sleep.  We structured the function to exit
+via standard err breaks, guaranteeing that l2tp_session_put() is cleanly
+called on all return paths to drop the reference.
+
+To preserve existing behavior we validate the session and its magic
+signature only for the specific L2TP commands that require it.  This
+ensures that generic/unknown ioctls called on an unconnected socket
+still return -ENOIOCTLCMD and correctly fall back to generic handlers
+(e.g. in sock_do_ioctl()).
+
+Signed-off-by: Lee Jones <lee@kernel.org>
+Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts")
+Link: https://patch.msgid.link/20260527133630.2120612-1-lee@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_ppp.c | 82 +++++++++++++++++++++++++++------------------
+ 1 file changed, 50 insertions(+), 32 deletions(-)
+
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index 5e12e7ce17d8a7..f388bf9abf378d 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -1044,64 +1044,76 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+ {
+       struct pppol2tp_ioc_stats stats;
+       struct l2tp_session *session;
++      int err = 0;
++
++      session = pppol2tp_sock_to_session(sock->sk);
++      /* Validate session presence and magic integrity ONLY for commands
++       * that belong to L2TP and require a valid session.
++       */
+       switch (cmd) {
+       case PPPIOCGMRU:
+       case PPPIOCGFLAGS:
+-              session = sock->sk->sk_user_data;
++      case PPPIOCSMRU:
++      case PPPIOCSFLAGS:
++      case PPPIOCGL2TPSTATS:
+               if (!session)
+                       return -ENOTCONN;
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
++              if (session->magic != L2TP_SESSION_MAGIC) {
++                      l2tp_session_put(session);
+                       return -EBADF;
++              }
++              break;
++      default:
++              break;
++      }
++      switch (cmd) {
++      case PPPIOCGMRU:
++      case PPPIOCGFLAGS:
+               /* Not defined for tunnels */
+-              if (!session->session_id && !session->peer_session_id)
+-                      return -ENOSYS;
++              if (!session->session_id && !session->peer_session_id) {
++                      err = -ENOSYS;
++                      break;
++              }
+-              if (put_user(0, (int __user *)arg))
+-                      return -EFAULT;
++              if (put_user(0, (int __user *)arg)) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       case PPPIOCSMRU:
+       case PPPIOCSFLAGS:
+-              session = sock->sk->sk_user_data;
+-              if (!session)
+-                      return -ENOTCONN;
+-
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
+-                      return -EBADF;
+-
+               /* Not defined for tunnels */
+-              if (!session->session_id && !session->peer_session_id)
+-                      return -ENOSYS;
++              if (!session->session_id && !session->peer_session_id) {
++                      err = -ENOSYS;
++                      break;
++              }
+-              if (!access_ok((int __user *)arg, sizeof(int)))
+-                      return -EFAULT;
++              if (!access_ok((int __user *)arg, sizeof(int))) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       case PPPIOCGL2TPSTATS:
+-              session = sock->sk->sk_user_data;
+-              if (!session)
+-                      return -ENOTCONN;
+-
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
+-                      return -EBADF;
+-
+               /* Session 0 represents the parent tunnel */
+               if (!session->session_id && !session->peer_session_id) {
+                       u32 session_id;
+-                      int err;
+                       if (copy_from_user(&stats, (void __user *)arg,
+-                                         sizeof(stats)))
+-                              return -EFAULT;
++                                         sizeof(stats))) {
++                              err = -EFAULT;
++                              break;
++                      }
+                       session_id = stats.session_id;
+                       err = pppol2tp_tunnel_copy_stats(&stats,
+                                                        session->tunnel);
+                       if (err < 0)
+-                              return err;
++                              break;
+                       stats.session_id = session_id;
+               } else {
+@@ -1111,15 +1123,21 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+               stats.tunnel_id = session->tunnel->tunnel_id;
+               stats.using_ipsec = l2tp_tunnel_uses_xfrm(session->tunnel);
+-              if (copy_to_user((void __user *)arg, &stats, sizeof(stats)))
+-                      return -EFAULT;
++              if (copy_to_user((void __user *)arg, &stats, sizeof(stats))) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       default:
+-              return -ENOIOCTLCMD;
++              err = -ENOIOCTLCMD;
++              break;
+       }
+-      return 0;
++      if (session)
++              l2tp_session_put(session);
++
++      return err;
+ }
+ /*****************************************************************************
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-6.18/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..cc3262c
--- /dev/null
@@ -0,0 +1,79 @@
+From 04782fd29e06d461bc89c20bbfb32b0effe51c6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index 23a88305f900cf..cb3535523bdffa 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -703,6 +703,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -753,6 +759,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch b/queue-6.18/net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch
new file mode 100644 (file)
index 0000000..7a6d4d0
--- /dev/null
@@ -0,0 +1,47 @@
+From 05402233e60d0b3b4ab86de6a3aa7f3390401bcd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:21:04 +0200
+Subject: net: airoha: Fix use-after-free in metadata dst teardown
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit b38cae85d1c45ff189d7ecb6ac36f41cdc3d84d0 ]
+
+airoha_metadata_dst_free() runs metadata_dst_free() which frees the
+metadata_dst with kfree() immediately, bypassing the RCU grace period.
+In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
+the skb to the metadata_dst. This function requires RCU read-side
+protection and the dst must remain valid until all RCU readers complete.
+Since metadata_dst_free() calls kfree() directly, an use-after-free can
+occur if any skb still holds a noref pointer to the dst when the driver
+tears it down.
+Replace metadata_dst_free() with dst_release() which properly goes
+through the refcount path: when the refcount drops to zero, it schedules
+the actual free via call_rcu_hurry(), ensuring all RCU readers have
+completed before the memory is freed.
+
+Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-1-3aaa99d83351@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
+index 9781a6fc9bf9a8..f30bace944d694 100644
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -2933,7 +2933,7 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
+               if (!port->dsa_meta[i])
+                       continue;
+-              metadata_dst_free(port->dsa_meta[i]);
++              dst_release(&port->dsa_meta[i]->dst);
+       }
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-annotate-sk-sk_write_space-for-udp-sockmap.patch b/queue-6.18/net-annotate-sk-sk_write_space-for-udp-sockmap.patch
new file mode 100644 (file)
index 0000000..0ccbb7b
--- /dev/null
@@ -0,0 +1,60 @@
+From a50c1d80bb40231998fee25a1a05df0d573a2fe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:39:23 +0000
+Subject: net: Annotate sk->sk_write_space() for UDP SOCKMAP.
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit b748765019fe9e9234660327090fc1a9665cdbdd ]
+
+UDP TX skb->destructor() is sock_wfree(), and UDP holds lock_sock()
+only for UDP_CORK / MSG_MORE sendmsg().
+
+Otherwise, sk->sk_write_space() may be read locklessly while SOCKMAP
+rewrites sk->sk_write_space().
+
+Let's use WRITE_ONCE() and READ_ONCE() for sk->sk_write_space().
+
+Note that the write side is annotated by commit 2ef2b20cf4e0
+("net: annotate data-races around sk->sk_{data_ready,write_space}").
+
+Fixes: 7b98cd42b049 ("bpf: sockmap: Add UDP support")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://patch.msgid.link/20260529193941.3897256-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 5a38837a583843..82470f59fa5c50 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2654,8 +2654,12 @@ void sock_wfree(struct sk_buff *skb)
+       bool free;
+       if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
++              void (*sk_write_space)(struct sock *sk);
++
++              sk_write_space = READ_ONCE(sk->sk_write_space);
++
+               if (sock_flag(sk, SOCK_RCU_FREE) &&
+-                  sk->sk_write_space == sock_def_write_space) {
++                  sk_write_space == sock_def_write_space) {
+                       rcu_read_lock();
+                       free = refcount_sub_and_test(len, &sk->sk_wmem_alloc);
+                       sock_def_write_space_wfree(sk);
+@@ -2670,7 +2674,7 @@ void sock_wfree(struct sk_buff *skb)
+                * after sk_write_space() call
+                */
+               WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
+-              sk->sk_write_space(sk);
++              sk_write_space(sk);
+               len = 1;
+       }
+       /*
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch b/queue-6.18/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
new file mode 100644 (file)
index 0000000..ef39eb7
--- /dev/null
@@ -0,0 +1,48 @@
+From f00fb5d5cb4fa0b36fec2b6080e902004cbb64f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:21:05 +0200
+Subject: net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst
+ teardown
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit 80df409e1a483676826a6c66e693dba6ac507751 ]
+
+mtk_free_dev() calls metadata_dst_free() which frees the metadata_dst
+with kfree() immediately, bypassing the RCU grace period.
+In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
+the skb to the metadata_dst. This function requires RCU read-side
+protection and the dst must remain valid until all RCU readers complete.
+Since metadata_dst_free() calls kfree() directly, a use-after-free can
+occur if any skb still holds a noref pointer to the dst when the driver
+tears it down.
+Replace metadata_dst_free() with dst_release() which properly goes
+through the refcount path: when the refcount drops to zero, it schedules
+the actual free via call_rcu_hurry(), ensuring all RCU readers have
+completed before the memory is freed.
+
+Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-2-3aaa99d83351@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index 0f676bd72832bb..065f969ee44ef6 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -4470,7 +4470,7 @@ static int mtk_free_dev(struct mtk_eth *eth)
+       for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
+               if (!eth->dsa_meta[i])
+                       break;
+-              metadata_dst_free(eth->dsa_meta[i]);
++              dst_release(&eth->dsa_meta[i]->dst);
+       }
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch b/queue-6.18/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
new file mode 100644 (file)
index 0000000..9b1b68d
--- /dev/null
@@ -0,0 +1,62 @@
+From e139f2b3a6ce64cd406813cab1c8fd0c0851be51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 06:18:57 +0000
+Subject: net: fec: fix pinctrl default state restore order on resume
+
+From: Tapio Reijonen <tapio.reijonen@vaisala.com>
+
+[ Upstream commit b455410146bf723c7ebcb49ecd5becc0d6611482 ]
+
+In fec_resume(), fec_enet_clk_enable() is called before
+pinctrl_pm_select_default_state() in the non-WoL path, inverting the
+ordering used in fec_suspend() which correctly switches to the sleep
+pinctrl state before disabling clocks.
+
+For PHYs with the PHY_RST_AFTER_CLK_EN flag (e.g. TI DP83848 or
+SMSC LAN87xx), fec_enet_clk_enable() triggers a hardware reset pulse
+via the phy-reset GPIO. With the GPIO pin still in sleep pinctrl state
+at that point, the GPIO write has no physical effect and the PHY never
+receives the required reset after clock enable, leading to unreliable
+link establishment after system resume.
+
+Fix by restoring the default pinctrl state before enabling clocks,
+making resume the proper mirror of suspend. The call is made
+unconditionally: fec_suspend() only switches to the sleep pinctrl state
+on the non-WoL path and leaves the pins in the default state when WoL
+is enabled, so on a WoL resume the device is already in the default
+state and pinctrl_pm_select_default_state() is a no-op.
+
+Fixes: de40ed31b3c5 ("net: fec: add Wake-on-LAN support")
+Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20260529-b4-fec-resume-pinctrl-order-v3-1-6eda0f592fca@vaisala.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index f30e8fabfaded8..a2cf8cbe2539ef 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -4772,6 +4772,7 @@ static int fec_resume(struct device *dev)
+               if (fep->rpm_active)
+                       pm_runtime_force_resume(dev);
++              pinctrl_pm_select_default_state(&fep->pdev->dev);
+               ret = fec_enet_clk_enable(ndev, true);
+               if (ret) {
+                       rtnl_unlock();
+@@ -4788,8 +4789,6 @@ static int fec_resume(struct device *dev)
+                       val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
+                       writel(val, fep->hwp + FEC_ECNTRL);
+                       fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
+-              } else {
+-                      pinctrl_pm_select_default_state(&fep->pdev->dev);
+               }
+               fec_restart(ndev);
+               netif_tx_lock_bh(ndev);
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-6.18/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..19e7b7e
--- /dev/null
@@ -0,0 +1,58 @@
+From 18d8333bf1e13db2e375bb54be7208460f68ccbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index 2d1ffc4d946266..c45abaff515364 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -453,7 +453,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-6.18/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..c130b49
--- /dev/null
@@ -0,0 +1,99 @@
+From b158e8e39ead4149b4d1357a5cfc494d2b28a7fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 09d255e78f6cd1..ab2f3c92b3fa33 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -1212,6 +1212,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -1251,6 +1281,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       eth_hw_addr_set(netdev, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 02a28b7091630d..b977256b742061 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -181,6 +181,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-6.18/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..e272eed
--- /dev/null
@@ -0,0 +1,106 @@
+From 5bc17a642f8c7723502699146b34b48af8801c32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index 2ba40eb45aad2f..a6d6f09dd0cd6a 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -45,6 +45,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *user_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index e1ab0faeb8113e..6afeeb6b590a2a 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -112,11 +112,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -129,7 +124,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void offload_action_hw_count_set(struct tc_action *act,
+-- 
+2.53.0
+
diff --git a/queue-6.18/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch b/queue-6.18/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
new file mode 100644 (file)
index 0000000..7ef9825
--- /dev/null
@@ -0,0 +1,228 @@
+From fac4018807ace9df79d4a7a057953c6c5385c7e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 08:32:21 -0400
+Subject: net/sched: fix pedit partial COW leading to page cache corruption
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
+
+[ Upstream commit 899ee91156e57784090c5565e4f31bd7dbffbc5a ]
+
+tcf_pedit_act() computes the COW range for skb_ensure_writable()
+once before the key loop using tcfp_off_max_hint, but the hint does
+not account for the runtime header offset added by typed keys. This
+can leave part of the write region un-COW'd.
+
+Fix by moving skb_ensure_writable() inside the per-key loop where
+the actual write offset is known, and add overflow checking on the
+offset arithmetic. For negative offsets (e.g. Ethernet header edits
+at ingress), use skb_cow() to COW the headroom instead. Guard
+offset_valid() against INT_MIN, where negation is undefined.
+
+Fixes: 8b796475fd78 ("net/sched: act_pedit: really ensure the skb is writable")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Reported-by: Keenan Dong <keenanat2000@gmail.com>
+Reported-by: Han Guidong <2045gemini@gmail.com>
+Reported-by: Zhang Cen <rollkingzzc@gmail.com>
+Reviewed-by: Han Guidong <2045gemini@gmail.com>
+Tested-by: Han Guidong <2045gemini@gmail.com>
+Reviewed-by: Davide Caratti <dcaratti@redhat.com>
+Tested-by: Davide Caratti <dcaratti@redhat.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Tested-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260531123221.48732-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tc_act/tc_pedit.h |  1 -
+ net/sched/act_pedit.c         | 77 +++++++++++++++++++----------------
+ 2 files changed, 41 insertions(+), 37 deletions(-)
+
+diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
+index f58ee15cd858cf..cb7b82f2cbc7fd 100644
+--- a/include/net/tc_act/tc_pedit.h
++++ b/include/net/tc_act/tc_pedit.h
+@@ -15,7 +15,6 @@ struct tcf_pedit_parms {
+       struct tc_pedit_key     *tcfp_keys;
+       struct tcf_pedit_key_ex *tcfp_keys_ex;
+       int action;
+-      u32 tcfp_off_max_hint;
+       unsigned char tcfp_nkeys;
+       unsigned char tcfp_flags;
+       struct rcu_head rcu;
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index 4b65901397a888..c0a5f5d78dacd9 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -16,6 +16,8 @@
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+ #include <linux/slab.h>
++#include <linux/overflow.h>
++#include <linux/unaligned.h>
+ #include <net/ipv6.h>
+ #include <net/netlink.h>
+ #include <net/pkt_sched.h>
+@@ -242,7 +244,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+               goto out_free_ex;
+       }
+-      nparms->tcfp_off_max_hint = 0;
+       nparms->tcfp_flags = parm->flags;
+       nparms->tcfp_nkeys = parm->nkeys;
+@@ -268,14 +269,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+                                                  BITS_PER_TYPE(int) - 1,
+                                                  nparms->tcfp_keys[i].shift);
+-              /* The AT option can read a single byte, we can bound the actual
+-               * value with uchar max.
+-               */
+-              cur += (0xff & offmask) >> nparms->tcfp_keys[i].shift;
+-
+-              /* Each key touches 4 bytes starting from the computed offset */
+-              nparms->tcfp_off_max_hint =
+-                      max(nparms->tcfp_off_max_hint, cur + 4);
+       }
+       p = to_pedit(*a);
+@@ -318,15 +311,12 @@ static void tcf_pedit_cleanup(struct tc_action *a)
+               call_rcu(&parms->rcu, tcf_pedit_cleanup_rcu);
+ }
+-static bool offset_valid(struct sk_buff *skb, int offset)
++static bool offset_valid(struct sk_buff *skb, int offset, int len)
+ {
+-      if (offset > 0 && offset > skb->len)
+-              return false;
+-
+-      if  (offset < 0 && -offset > skb_headroom(skb))
++      if (offset < -(int)skb_headroom(skb))
+               return false;
+-      return true;
++      return offset <= (int)skb->len - len;
+ }
+ static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int header_type)
+@@ -393,18 +383,10 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+       struct tcf_pedit_key_ex *tkey_ex;
+       struct tcf_pedit_parms *parms;
+       struct tc_pedit_key *tkey;
+-      u32 max_offset;
+       int i;
+       parms = rcu_dereference_bh(p->parms);
+-      max_offset = (skb_transport_header_was_set(skb) ?
+-                    skb_transport_offset(skb) :
+-                    skb_network_offset(skb)) +
+-                   parms->tcfp_off_max_hint;
+-      if (skb_ensure_writable(skb, min(skb->len, max_offset)))
+-              goto done;
+-
+       tcf_lastuse_update(&p->tcf_tm);
+       tcf_action_update_bstats(&p->common, skb);
+@@ -412,10 +394,11 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+       tkey_ex = parms->tcfp_keys_ex;
+       for (i = parms->tcfp_nkeys; i > 0; i--, tkey++) {
++              int write_offset, write_len;
+               int offset = tkey->off;
+               int hoffset = 0;
+-              u32 *ptr, hdata;
+-              u32 val;
++              u32 cur_val, val;
++              u32 *ptr;
+               int rc;
+               if (tkey_ex) {
+@@ -433,13 +416,15 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+               if (tkey->offmask) {
+                       u8 *d, _d;
++                      int at_offset;
+-                      if (!offset_valid(skb, hoffset + tkey->at)) {
++                      if (check_add_overflow(hoffset, (int)tkey->at, &at_offset) ||
++                          !offset_valid(skb, at_offset, sizeof(_d))) {
+                               pr_info_ratelimited("tc action pedit 'at' offset %d out of bounds\n",
+                                                   hoffset + tkey->at);
+                               goto bad;
+                       }
+-                      d = skb_header_pointer(skb, hoffset + tkey->at,
++                      d = skb_header_pointer(skb, at_offset,
+                                              sizeof(_d), &_d);
+                       if (!d)
+                               goto bad;
+@@ -451,31 +436,51 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+                       }
+               }
+-              if (!offset_valid(skb, hoffset + offset)) {
+-                      pr_info_ratelimited("tc action pedit offset %d out of bounds\n", hoffset + offset);
++              if (check_add_overflow(hoffset, offset, &write_offset)) {
++                      pr_info_ratelimited("tc action pedit offset overflow\n");
+                       goto bad;
+               }
+-              ptr = skb_header_pointer(skb, hoffset + offset,
+-                                       sizeof(hdata), &hdata);
+-              if (!ptr)
++              if (!offset_valid(skb, write_offset, sizeof(*ptr))) {
++                      pr_info_ratelimited("tc action pedit offset %d out of bounds\n",
++                                          write_offset);
+                       goto bad;
++              }
++
++              if (write_offset < 0) {
++                      if (skb_cow(skb, -write_offset))
++                              goto bad;
++                      if (write_offset + (int)sizeof(*ptr) > 0) {
++                              if (skb_ensure_writable(skb,
++                                                      min_t(int, skb->len,
++                                                            write_offset + (int)sizeof(*ptr))))
++                                      goto bad;
++                      }
++              } else {
++                      if (check_add_overflow(write_offset, (int)sizeof(*ptr),
++                                             &write_len))
++                              goto bad;
++                      if (skb_ensure_writable(skb, min_t(int, skb->len,
++                                                         write_len)))
++                              goto bad;
++              }
++
++              ptr = (u32 *)(skb->data + write_offset);
++              cur_val = get_unaligned(ptr);
+               /* just do it, baby */
+               switch (cmd) {
+               case TCA_PEDIT_KEY_EX_CMD_SET:
+                       val = tkey->val;
+                       break;
+               case TCA_PEDIT_KEY_EX_CMD_ADD:
+-                      val = (*ptr + tkey->val) & ~tkey->mask;
++                      val = (cur_val + tkey->val) & ~tkey->mask;
+                       break;
+               default:
+                       pr_info_ratelimited("tc action pedit bad command (%d)\n", cmd);
+                       goto bad;
+               }
+-              *ptr = ((*ptr & tkey->mask) ^ val);
+-              if (ptr == &hdata)
+-                      skb_store_bits(skb, hoffset + offset, ptr, 4);
++              put_unaligned((cur_val & tkey->mask) ^ val, ptr);
+       }
+       goto done;
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-6.18/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..53e5fd1
--- /dev/null
@@ -0,0 +1,58 @@
+From b1a2b3bcaccbb935f7fd7e51be84ea706a610a4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-6.18/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..75c9e51
--- /dev/null
@@ -0,0 +1,50 @@
+From 786bfe9682326739d8421044871768a405a813fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index 5703846bea3b69..0f50ea92ced9df 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -208,7 +208,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -222,7 +222,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch b/queue-6.18/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
new file mode 100644 (file)
index 0000000..819dbcc
--- /dev/null
@@ -0,0 +1,96 @@
+From a1b7aaa8c64e714a26658b65f16cde95eef8282c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:09:19 +0800
+Subject: netfilter: nft_ct: bail out on template ct in get eval
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 3027ecbdb5fdf9200251c21d4818e4c447ef78e1 ]
+
+I noticed this issue while looking at a historic syzbot report [1].
+
+A rule like the one below is enough to trigger the bug:
+
+    table ip t {
+        chain pre {
+            type filter hook prerouting priority raw;
+            ct zone set 1
+            ct original saddr 1.2.3.4 accept
+        }
+    }
+
+The first expression attaches a per-cpu template ct via
+nft_ct_set_zone_eval() (nf_ct_tmpl_alloc -> kzalloc, tuple is all
+zero, nf_ct_l3num(ct) == 0). The next expression then calls
+nft_ct_get_eval() on the same skb, treats the template as a real ct
+and hits the 16-byte memcpy path. With dreg at NFT_REG32_15 this
+overflows past struct nft_regs on the kernel stack; with smaller
+dreg values it silently clobbers adjacent registers.
+
+Reject template ct at the eval entry and in nft_ct_get_fast_eval(),
+mirroring the check nft_ct_set_eval() already has. Additionally,
+bound the address copy in NFT_CT_SRC / NFT_CT_DST by priv->len
+instead of by nf_ct_l3num(ct): nf_ct_get_tuple() zeroes the tuple
+before pkt_to_tuple() fills in only the protocol-relevant leading
+bytes, so the trailing bytes of tuple->{src,dst}.u3.all are
+well-defined zero. priv->len is validated at rule load, so the
+copy size is now bounded by the destination register rather than
+by an untrusted field on the conntrack.
+
+[1]: https://syzkaller.appspot.com/bug?id=389cf09cb72926114fce90dc85a2c3231dcb647c
+
+Fixes: 45d9bcda21f4 ("netfilter: nf_tables: validate len in nft_validate_data_load()")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+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>
+---
+ net/netfilter/nft_ct.c      | 8 +++-----
+ net/netfilter/nft_ct_fast.c | 2 +-
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 8dbf31e7ddcbee..c776eb38f1dbd0 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -78,7 +78,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (ct == NULL)
++      if (!ct || nf_ct_is_template(ct))
+               goto err;
+       switch (priv->key) {
+@@ -180,12 +180,10 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+       tuple = &ct->tuplehash[priv->dir].tuple;
+       switch (priv->key) {
+       case NFT_CT_SRC:
+-              memcpy(dest, tuple->src.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->src.u3.all, priv->len);
+               return;
+       case NFT_CT_DST:
+-              memcpy(dest, tuple->dst.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->dst.u3.all, priv->len);
+               return;
+       case NFT_CT_PROTO_SRC:
+               nft_reg_store16(dest, (__force u16)tuple->src.u.all);
+diff --git a/net/netfilter/nft_ct_fast.c b/net/netfilter/nft_ct_fast.c
+index e684c8a9184877..ecf7b3a404be26 100644
+--- a/net/netfilter/nft_ct_fast.c
++++ b/net/netfilter/nft_ct_fast.c
+@@ -30,7 +30,7 @@ void nft_ct_get_fast_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (!ct) {
++      if (!ct || nf_ct_is_template(ct)) {
+               regs->verdict.code = NFT_BREAK;
+               return;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-6.18/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..b16738c
--- /dev/null
@@ -0,0 +1,113 @@
+From 79673a3d724836387c6f300e69f297f396d392b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 6a851ac4dd048f..a277b2bd3275dc 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -21,6 +21,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -768,26 +770,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1192,27 +1199,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-6.18/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-6.18/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..e15b239
--- /dev/null
@@ -0,0 +1,41 @@
+From 0b1c475da74b3ff4272ed64fe557696342fe74c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-6.18/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch b/queue-6.18/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch
new file mode 100644 (file)
index 0000000..e3997ce
--- /dev/null
@@ -0,0 +1,44 @@
+From 33e514b0762e666745ffa3a500304af7799a183c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 17:07:05 +0530
+Subject: octeontx2-af: Fix initialization of mcam's entry2target_pffunc field
+
+From: Suman Ghosh <sumang@marvell.com>
+
+[ Upstream commit 9a85ec3dc28b6df246801c19e4d9bae6297a25b0 ]
+
+NPC mcam entry stores a mapping between mcam entry and target pcifunc.
+During initialization of this field, API kmalloc_array has been used which
+caused some junk values to array. Whereas, the array is expected to be
+initialized by 0. This patch fixes the same by using kcalloc instead of
+kmalloc_array.
+
+Fixes: 55307fcb9258 ("octeontx2-af: Add mbox messages to install and delete MCAM rules")
+Signed-off-by: Suman Ghosh <sumang@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/1780054625-17090-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index e28675fe189071..a0d2ed56186d8d 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -1932,8 +1932,8 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
+               goto free_entry_cntr_map;
+       /* Alloc memory for saving target device of mcam rule */
+-      mcam->entry2target_pffunc = kmalloc_array(mcam->total_entries,
+-                                                sizeof(u16), GFP_KERNEL);
++      mcam->entry2target_pffunc = kcalloc(mcam->total_entries,
++                                          sizeof(u16), GFP_KERNEL);
+       if (!mcam->entry2target_pffunc)
+               goto free_cntr_refcnt;
+-- 
+2.53.0
+
diff --git a/queue-6.18/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch b/queue-6.18/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
new file mode 100644 (file)
index 0000000..00b95e0
--- /dev/null
@@ -0,0 +1,119 @@
+From d4eaf888f8e21c70415d933cd5020ece26cbbc3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 10:28:53 +0530
+Subject: octeontx2-af: npc: Fix CPT channel mask in npc_install_flow
+
+From: Nithin Dabilpuram <ndabilpuram@marvell.com>
+
+[ Upstream commit 1d31eb27e570daa04f5373345f9ac98c95863be9 ]
+
+Use the CPT-aware NIX channel mask in the npc_install_flow path so that
+when the host PF installs steering rules in kernel for a VF used from
+userspace (e.g. DPDK), MCAM entries see the same channel mask semantics as
+other RX paths.
+
+Fixes: 56bcef528bd8 ("octeontx2-af: Use npc_install_flow API for promisc and broadcast entries")
+Cc: Naveen Mamindlapalli <naveenm@marvell.com>
+Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
+Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
+Link: https://patch.msgid.link/20260602045853.1558530-1-rkannoth@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |  1 +
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   | 32 +++++++++----------
+ .../marvell/octeontx2/af/rvu_npc_fs.c         |  2 +-
+ 3 files changed, 18 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index b5828334192324..914ba2b691ec80 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -1124,6 +1124,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
+                       int slot);
+ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);
+ int rvu_cpt_init(struct rvu *rvu);
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu);
+ #define NDC_AF_BANK_MASK       GENMASK_ULL(7, 0)
+ #define NDC_AF_BANK_LINE_MASK  GENMASK_ULL(31, 16)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index a0d2ed56186d8d..65aa6aeab8e782 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -599,6 +599,19 @@ void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
+                          NPC_AF_MCAMEX_BANKX_ACTION(index, bank), cfg);
+ }
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu)
++{
++      /* For cn10k the upper two bits of the channel number are
++       * cpt channel number. with masking out these bits in the
++       * mcam entry, same entry used for NIX will allow packets
++       * received from cpt for parsing.
++       */
++      if (!is_rvu_otx2(rvu))
++              return NIX_CHAN_CPT_X2P_MASK;
++      else
++              return 0xFFFu;
++}
++
+ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+                                int nixlf, u64 chan, u8 *mac_addr)
+ {
+@@ -642,7 +655,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+       eth_broadcast_addr((u8 *)&req.mask.dmac);
+       req.features = BIT_ULL(NPC_DMAC);
+       req.channel = chan;
+-      req.chan_mask = 0xFFFU;
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.intf = pfvf->nix_rx_intf;
+       req.op = action.op;
+       req.hdr.pcifunc = 0; /* AF is requester */
+@@ -712,11 +725,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+        * mcam entry, same entry used for NIX will allow packets
+        * received from cpt for parsing.
+        */
+-      if (!is_rvu_otx2(rvu)) {
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      } else {
+-              req.chan_mask = 0xFFFU;
+-      }
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       if (chan_cnt > 1) {
+               if (!is_power_of_2(chan_cnt)) {
+@@ -887,16 +896,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+       ether_addr_copy(req.mask.dmac, mac_addr);
+       req.features = BIT_ULL(NPC_DMAC);
+-      /* For cn10k the upper two bits of the channel number are
+-       * cpt channel number. with masking out these bits in the
+-       * mcam entry, same entry used for NIX will allow packets
+-       * received from cpt for parsing.
+-       */
+-      if (!is_rvu_otx2(rvu))
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      else
+-              req.chan_mask = 0xFFFU;
+-
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.channel = chan;
+       req.intf = pfvf->nix_rx_intf;
+       req.entry = index;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+index b56395ac5a7439..e0262fcedd8984 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+@@ -1470,7 +1470,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
+       /* ignore chan_mask in case pf func is not AF, revisit later */
+       if (!is_pffunc_af(req->hdr.pcifunc))
+-              req->chan_mask = 0xFFF;
++              req->chan_mask = rvu_get_cpt_chan_mask(rvu);
+       err = npc_check_unsupported_flows(rvu, req->features, req->intf);
+       if (err)
+-- 
+2.53.0
+
diff --git a/queue-6.18/octeontx2-pf-fix-ndc-sync-operation-errors.patch b/queue-6.18/octeontx2-pf-fix-ndc-sync-operation-errors.patch
new file mode 100644 (file)
index 0000000..c96b5fc
--- /dev/null
@@ -0,0 +1,40 @@
+From 358de501dee14efe74efbfa661e02ac670f93ab1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 17:07:57 +0530
+Subject: octeontx2-pf: Fix NDC sync operation errors
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit a910fb8f7b9e4c566db363e6c2ec378dc7153995 ]
+
+On system reboot "rvu_nicpf 0002:03:00.0: NDC sync operation failed"
+error messages are shown, even if the operations is successful.
+This is due to wrong if error check in ndc_syc() function.
+
+Fixes: 42c45ac1419c ("octeontx2-af: Sync NIX and NPA contexts from NDC to LLC/DRAM")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/1780054677-17249-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index bbf25769f4994a..fa23d42d1318b4 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -3481,7 +3481,7 @@ static void otx2_ndc_sync(struct otx2_nic *pf)
+       req->nix_lf_rx_sync = 1;
+       req->npa_lf_sync = 1;
+-      if (!otx2_sync_mbox_msg(mbox))
++      if (otx2_sync_mbox_msg(mbox))
+               dev_err(pf->dev, "NDC sync operation failed\n");
+       mutex_unlock(&mbox->lock);
+-- 
+2.53.0
+
diff --git a/queue-6.18/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-6.18/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..6b4d375
--- /dev/null
@@ -0,0 +1,58 @@
+From 48727ee140080c6d4e8568375410b3cad8dbd5af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 9eaefa0f5e80c5..b465bb77432194 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1407,8 +1407,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1416,9 +1418,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/ptp-vclock-switch-from-rcu-to-srcu.patch b/queue-6.18/ptp-vclock-switch-from-rcu-to-srcu.patch
new file mode 100644 (file)
index 0000000..89d88df
--- /dev/null
@@ -0,0 +1,85 @@
+From 6f33ef20cd374d326208db9f1263a2dbce5df8e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:11:47 +0200
+Subject: ptp: vclock: Switch from RCU to SRCU
+
+From: Kurt Kanzenbach <kurt@linutronix.de>
+
+[ Upstream commit 672bd0519e27c357c43b7f8c0d653fce3817d06e ]
+
+The usage of PTP vClocks leads immediately to the following issues with
+ptp4l with LOCKDEP and DEBUG_ATOMIC_SLEEP enabled: "BUG: sleeping function
+called from invalid context".
+
+ptp_convert_timestamp() acquires a mutex_t within a RCU read section.  This
+is illegal, because acquiring a mutex_t can result in voluntary scheduling
+request which is not allowed within a RCU read section.
+
+Replace the RCU usage with SRCU where sleeping is allowed.
+
+Reported-by: Florian Zeitz <florian.zeitz@schettke.com>
+Closes: https://lore.kernel.org/all/00a8cce8-410e-4038-98af-49be6d93d7bd@schettke.com/
+Fixes: 67d93ffc0f3c ("ptp: vclock: use mutex to fix "sleep on atomic" bug")
+Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260529-vclock_rcu-v2-1-02a5531fab92@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_vclock.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
+index 64c95045651787..295a64bdd846f2 100644
+--- a/drivers/ptp/ptp_vclock.c
++++ b/drivers/ptp/ptp_vclock.c
+@@ -19,6 +19,8 @@ static DEFINE_SPINLOCK(vclock_hash_lock);
+ static DEFINE_READ_MOSTLY_HASHTABLE(vclock_hash, 8);
++DEFINE_STATIC_SRCU(vclock_srcu);
++
+ static void ptp_vclock_hash_add(struct ptp_vclock *vclock)
+ {
+       spin_lock(&vclock_hash_lock);
+@@ -37,7 +39,7 @@ static void ptp_vclock_hash_del(struct ptp_vclock *vclock)
+       spin_unlock(&vclock_hash_lock);
+-      synchronize_rcu();
++      synchronize_srcu(&vclock_srcu);
+ }
+ static int ptp_vclock_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+@@ -276,14 +278,16 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+ {
+       unsigned int hash = vclock_index % HASH_SIZE(vclock_hash);
+       struct ptp_vclock *vclock;
+-      u64 ns;
+       u64 vclock_ns = 0;
++      int srcu_idx;
++      u64 ns;
+       ns = ktime_to_ns(*hwtstamp);
+-      rcu_read_lock();
++      srcu_idx = srcu_read_lock(&vclock_srcu);
+-      hlist_for_each_entry_rcu(vclock, &vclock_hash[hash], vclock_hash_node) {
++      hlist_for_each_entry_srcu(vclock, &vclock_hash[hash], vclock_hash_node,
++                                srcu_read_lock_held(&vclock_srcu)) {
+               if (vclock->clock->index != vclock_index)
+                       continue;
+@@ -294,7 +298,7 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+               break;
+       }
+-      rcu_read_unlock();
++      srcu_read_unlock(&vclock_srcu, srcu_idx);
+       return ns_to_ktime(vclock_ns);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-6.18/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..d780f95
--- /dev/null
@@ -0,0 +1,87 @@
+From bac7c58ed1d278e2f5fbc13ee5e5fe6c80a7f801 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 8e89a870780c49..9b23c11cbb9ea4 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2598,11 +2598,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
diff --git a/queue-6.18/sctp-validate-cached-peer-init-chunk-length-in-cooki.patch b/queue-6.18/sctp-validate-cached-peer-init-chunk-length-in-cooki.patch
new file mode 100644 (file)
index 0000000..251b8fc
--- /dev/null
@@ -0,0 +1,61 @@
+From faeef7ac112e041e07ae1c629a5117c03299af33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 21:06:06 -0400
+Subject: sctp: validate cached peer INIT chunk length in COOKIE_ECHO
+ processing
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 0861615c28de668669d748ef4eb913ea9262d13b ]
+
+When a listening SCTP server processes a COOKIE_ECHO chunk, the cached
+peer INIT chunk embedded after the cookie is parsed and its parameters
+are later walked by sctp_process_init() using sctp_walk_params().
+
+However, the chunk header length of this cached INIT chunk was not
+validated against the remaining buffer in the COOKIE_ECHO payload. If
+the length field is inflated, the parameter walk can run beyond the
+actual received data, leading to out-of-bounds reads and potential
+memory corruption during later parameter handling (e.g. STATE_COOKIE
+processing and kmemdup() copies).
+
+Add a bounds check in sctp_unpack_cookie() to ensure the cached INIT
+chunk length does not exceed the available data in the COOKIE_ECHO
+buffer before it is used.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Brian Geffon <bgeffon@google.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/eb60825fa22d6f9e663c7d4dbb69f397b5d34d42.1780362366.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 2c0017d058d409..9014b095f52ddb 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -1730,6 +1730,7 @@ struct sctp_association *sctp_unpack_cookie(
+       struct sctp_signed_cookie *cookie;
+       struct sk_buff *skb = chunk->skb;
+       struct sctp_cookie *bear_cookie;
++      struct sctp_chunkhdr *ch;
+       enum sctp_scope scope;
+       unsigned int len;
+       ktime_t kt;
+@@ -1759,6 +1760,10 @@ struct sctp_association *sctp_unpack_cookie(
+       cookie = chunk->subh.cookie_hdr;
+       bear_cookie = &cookie->c;
++      ch = (struct sctp_chunkhdr *)(bear_cookie + 1);
++      if (ntohs(ch->length) > len - fixed_size)
++              goto malformed;
++
+       /* Verify the cookie's MAC, if cookie authentication is enabled. */
+       if (sctp_sk(ep->base.sk)->cookie_auth_enable) {
+               u8 mac[SHA256_DIGEST_SIZE];
+-- 
+2.53.0
+
index 3a3e22f74346ba33ebf33908dbbfca063115e288..03e135d42461d70f19e8e3d82d72c0cb07157b79 100644 (file)
@@ -3,3 +3,62 @@ arm-group-is_permission_fault-with-is_translation_fa.patch
 arm-allow-__do_kernel_fault-to-report-execution-of-m.patch
 arm-fix-hash_name-fault.patch
 arm-fix-branch-predictor-hardening.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch
+arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch
+arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch
+soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch
+tee-fix-tee_ioctl_object_invoke_arg-padding.patch
+tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch
+erofs-tidy-up-synchronous-decompression.patch
+erofs-fix-use-after-free-on-sbi-sync_decompress.patch
+wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch
+ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch
+devlink-release-nested-relation-on-devlink-free.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-annotate-sk-sk_write_space-for-udp-sockmap.patch
+hsr-remove-warn_once-in-hsr_addr_is_self.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
+ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch
+wifi-fix-leak-if-split-6-ghz-scanning-fails.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
+bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
+bluetooth-bnep-reject-short-frames-before-parsing.patch
+bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
+bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch
+bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch
+bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch
+bluetooth-mgmt-fix-backward-compatibility-with-users.patch
+xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch
+octeontx2-pf-fix-ndc-sync-operation-errors.patch
+octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch
+af_unix-fix-inq_len-update-problem-in-partial-read.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ptp-vclock-switch-from-rcu-to-srcu.patch
+net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch
+net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
+net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
+sctp-validate-cached-peer-init-chunk-length-in-cooki.patch
+octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
+vxlan-vnifilter-send-notification-on-vni-add.patch
+vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
+ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
diff --git a/queue-6.18/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch b/queue-6.18/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch
new file mode 100644 (file)
index 0000000..0fdeb96
--- /dev/null
@@ -0,0 +1,87 @@
+From fc7202ea6aa440a60f11f1721cc8df9e4c0a8f4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Apr 2026 17:29:19 +0530
+Subject: soc: qcom: ice: Allow explicit votes on 'iface' clock for ICE
+
+From: Harshal Dev <harshal.dev@oss.qualcomm.com>
+
+[ Upstream commit 0d5dc5818191b55e4364d04b1b898a14a2ccac38 ]
+
+Since Qualcomm inline-crypto engine (ICE) is now a dedicated driver
+de-coupled from the QCOM UFS driver, it explicitly votes for its required
+clocks during probe. For scenarios where the 'clk_ignore_unused' flag is
+not passed on the kernel command line, to avoid potential unclocked ICE
+hardware register access during probe the ICE driver should additionally
+vote on the 'iface' clock.
+Also update the suspend and resume callbacks to handle un-voting and voting
+on the 'iface' clock.
+
+Fixes: 2afbf43a4aec6 ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver")
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Reviewed-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-2-5ccf5d7e2846@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index c467b55b41744e..05055e097ff8fb 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -95,6 +95,7 @@ struct qcom_ice {
+       void __iomem *base;
+       struct clk *core_clk;
++      struct clk *iface_clk;
+       bool use_hwkm;
+       bool hwkm_init_complete;
+ };
+@@ -278,8 +279,13 @@ int qcom_ice_resume(struct qcom_ice *ice)
+       err = clk_prepare_enable(ice->core_clk);
+       if (err) {
+-              dev_err(dev, "failed to enable core clock (%d)\n",
+-                      err);
++              dev_err(dev, "Failed to enable core clock: %d\n", err);
++              return err;
++      }
++
++      err = clk_prepare_enable(ice->iface_clk);
++      if (err) {
++              dev_err(dev, "Failed to enable iface clock: %d\n", err);
+               return err;
+       }
+       qcom_ice_hwkm_init(ice);
+@@ -289,6 +295,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
+ int qcom_ice_suspend(struct qcom_ice *ice)
+ {
++      clk_disable_unprepare(ice->iface_clk);
+       clk_disable_unprepare(ice->core_clk);
+       ice->hwkm_init_complete = false;
+@@ -544,11 +551,17 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
+       engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_optional_enabled(dev, "ice");
++      if (!engine->core_clk)
++              engine->core_clk = devm_clk_get_optional_enabled(dev, "core");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_enabled(dev, NULL);
+       if (IS_ERR(engine->core_clk))
+               return ERR_CAST(engine->core_clk);
++      engine->iface_clk = devm_clk_get_optional_enabled(dev, "iface");
++      if (IS_ERR(engine->iface_clk))
++              return ERR_CAST(engine->iface_clk);
++
+       if (!qcom_ice_check_supported(engine))
+               return ERR_PTR(-EOPNOTSUPP);
+-- 
+2.53.0
+
diff --git a/queue-6.18/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch b/queue-6.18/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch
new file mode 100644 (file)
index 0000000..806f71d
--- /dev/null
@@ -0,0 +1,44 @@
+From 16c1f6d52fabb42a66fd20ba426e0ff3ae230527 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 May 2026 19:22:18 +0530
+Subject: soc: qcom: ice: Return -ENODEV if the ICE platform device is not
+ found
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+
+[ Upstream commit 5a4dc805a80e6fe303d6a4748cd451ea15987ffd ]
+
+By the time the consumer driver calls devm_of_qcom_ice_get(), all the
+platform devices for ICE nodes would've been created by
+of_platform_default_populate().
+
+So for the absence of any platform device, -ENODEV should not returned, not
+-EPROBE_DEFER.
+
+Fixes: 2afbf43a4aec ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver")
+Tested-by: Sumit Garg <sumit.garg@oss.qualcomm.com> # OP-TEE as TZ
+Acked-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260518-qcom-ice-fix-v7-2-2a595382185b@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index 05055e097ff8fb..ba53aea828ba76 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -622,7 +622,7 @@ static struct qcom_ice *of_qcom_ice_get(struct device *dev)
+       pdev = of_find_device_by_node(node);
+       if (!pdev) {
+               dev_err(dev, "Cannot find device node %s\n", node->name);
+-              return ERR_PTR(-EPROBE_DEFER);
++              return ERR_PTR(-ENODEV);
+       }
+       ice = platform_get_drvdata(pdev);
+-- 
+2.53.0
+
diff --git a/queue-6.18/tee-fix-tee_ioctl_object_invoke_arg-padding.patch b/queue-6.18/tee-fix-tee_ioctl_object_invoke_arg-padding.patch
new file mode 100644 (file)
index 0000000..f4cd84e
--- /dev/null
@@ -0,0 +1,44 @@
+From 5d030a4a8344f340e5d04a5d0b30e2b857eb6474 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Dec 2025 11:17:23 +0100
+Subject: tee: fix tee_ioctl_object_invoke_arg padding
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit c15d7a2a11ea055bcecc0b538ae8ba79475637f9 ]
+
+The tee_ioctl_object_invoke_arg structure has padding on some
+architectures but not on x86-32 and a few others:
+
+include/linux/tee.h:474:32: error: padding struct to align 'params' [-Werror=padded]
+
+I expect that all current users of this are on architectures that do
+have implicit padding here (arm64, arm, x86, riscv), so make the padding
+explicit in order to avoid surprises if this later gets used elsewhere.
+
+Fixes: d5b8b0fa1775 ("tee: add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
+Tested-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/tee.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
+index cab5cadca8ef99..5203977ed35d1d 100644
+--- a/include/uapi/linux/tee.h
++++ b/include/uapi/linux/tee.h
+@@ -470,6 +470,7 @@ struct tee_ioctl_object_invoke_arg {
+       __u32 op;
+       __u32 ret;
+       __u32 num_params;
++      __u32 :32;
+       /* num_params tells the actual number of element in params */
+       struct tee_ioctl_param params[];
+ };
+-- 
+2.53.0
+
diff --git a/queue-6.18/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-6.18/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..8f3e3b4
--- /dev/null
@@ -0,0 +1,287 @@
+From 947a5698797496b8de1a3c791f32d7ed81a53897 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index d0f397c9024201..2386bbd38ce78b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch b/queue-6.18/tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch
new file mode 100644 (file)
index 0000000..d2f68d6
--- /dev/null
@@ -0,0 +1,47 @@
+From c56c0c17c2ae653224443f1ee988eba441ac8b83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 09:05:28 +0700
+Subject: tee: qcomtee: add missing va_end in early return
+ qcomtee_object_user_init()
+
+From: Robertus Diawan Chris <robertusdchris@gmail.com>
+
+[ Upstream commit 471c18323dfdfe7844e193b896a9267ae23a1026 ]
+
+qcomtee_object_user_init() is a variadic function and when the function
+return because there's no dispatch callback in QCOMTEE_OBJECT_TYPE_CB
+case, there's no va_end to cleanup "ap" object initialized by va_start
+and that can cause undefined behavior. So make sure to use va_end before
+returning the error code when there's no dispatch callback.
+
+This is reported by Coverity Scan as "Missing varargs init or cleanup".
+
+Fixes: d6e290837e50 ("tee: add Qualcomm TEE driver")
+Signed-off-by: Robertus Diawan Chris <robertusdchris@gmail.com>
+Reviewed-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/qcomtee/core.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tee/qcomtee/core.c b/drivers/tee/qcomtee/core.c
+index ecd04403591cf9..10717434275b1b 100644
+--- a/drivers/tee/qcomtee/core.c
++++ b/drivers/tee/qcomtee/core.c
+@@ -306,8 +306,10 @@ int qcomtee_object_user_init(struct qcomtee_object *object,
+               break;
+       case QCOMTEE_OBJECT_TYPE_CB:
+               object->ops = ops;
+-              if (!object->ops->dispatch)
+-                      return -EINVAL;
++              if (!object->ops->dispatch) {
++                      ret = -EINVAL;
++                      break;
++              }
+               /* If failed, "no-name". */
+               object->name = kvasprintf_const(GFP_KERNEL, fmt, ap);
+-- 
+2.53.0
+
diff --git a/queue-6.18/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch b/queue-6.18/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
new file mode 100644 (file)
index 0000000..e52ba46
--- /dev/null
@@ -0,0 +1,55 @@
+From 8b81d60d52fa8488c61da8f97ec7de19d85c3e65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:37 -0700
+Subject: vxlan: vnifilter: fix spurious notification on VNI update
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit 84683b5b60c7274e2c8f7f413d39d78d3db5540f ]
+
+When a VNI is re-added with the same attributes (e.g. same group or no
+group), vxlan_vni_update() sends a spurious RTM_NEWTUNNEL notification
+even though nothing changed.
+
+The bug is that 'if (changed)' tests whether the pointer is non-NULL,
+not the bool value it points to. Since every caller passes a valid
+pointer, the condition is always true and the notification fires
+unconditionally.
+
+Fix by dereferencing the pointer: 'if (*changed)'.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100
+ # bridge vni add vni 1000 dev vxlan100  # spurious notification
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-3-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index 43c70c395b58e5..215e82876662de 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -661,7 +661,7 @@ static int vxlan_vni_update(struct vxlan_dev *vxlan,
+       if (ret)
+               return ret;
+-      if (changed)
++      if (*changed)
+               vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.18/vxlan-vnifilter-send-notification-on-vni-add.patch b/queue-6.18/vxlan-vnifilter-send-notification-on-vni-add.patch
new file mode 100644 (file)
index 0000000..ca178d9
--- /dev/null
@@ -0,0 +1,69 @@
+From b2d790101ee7097912598ceaaaff98c64fe391b2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:36 -0700
+Subject: vxlan: vnifilter: send notification on VNI add
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit aa6ca1c5c338907817374b59f7551fd855a88754 ]
+
+When a new VNI is added to a vxlan device with vnifilter enabled,
+no RTM_NEWTUNNEL notification is sent to userspace. This means
+'bridge monitor vni' never shows VNI add events, even though
+VNI delete events are reported correctly.
+
+The bug is in vxlan_vni_add(), where the notification is guarded by
+'if (changed)'. The 'changed' flag is set by vxlan_vni_update_group()
+only when the multicast group or remote IP is modified, but for a
+new VNI added without a group (e.g. in L3 VxLAN interface scenarios),
+the function returns early without setting changed=true. Since this
+is a new VNI, the notification should be sent unconditionally.
+
+The notification is not guarded by the return value of
+vxlan_vni_update_group() because, at this point, the VNI has already
+been inserted into the hash table and list with no rollback on error.
+The VNI will be visible in 'bridge vni show' regardless, so userspace
+should be informed. This is consistent with vxlan_vni_del() which also
+notifies unconditionally.
+
+The 'if (changed)' guard remains correct in vxlan_vni_update(), which
+handles the case where a VNI already exists and is being re-added --
+there, we only want to notify if the group/remote actually changed.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100    # no notification
+ # bridge vni delete vni 1000 dev vxlan100 # notification received
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Reported-by: Chirag Shah <chirag@nvidia.com>
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-2-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index adc89e651e27c8..43c70c395b58e5 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -759,8 +759,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+       err = vxlan_vni_update_group(vxlan, vninode, group, true, &changed,
+                                    extack);
+-      if (changed)
+-              vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
++      vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return err;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.18/wifi-fix-leak-if-split-6-ghz-scanning-fails.patch b/queue-6.18/wifi-fix-leak-if-split-6-ghz-scanning-fails.patch
new file mode 100644 (file)
index 0000000..a8f2d9d
--- /dev/null
@@ -0,0 +1,79 @@
+From e5e32608acb284f934201381a8a5dcc97316b087 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:41:56 +0300
+Subject: wifi: fix leak if split 6 GHz scanning fails
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+[ Upstream commit e8694f7cc29287e843648d1075177b9a2000d957 ]
+
+rdev->int_scan_req is leaked if cfg80211_scan() fails.  Note that it's
+supposed to be released at ___cfg80211_scan_done() but this doesn't happen
+as rdev->scan_req is NULL at that point, too, leading to the early return
+from the freeing function.
+
+unreferenced object 0xffff8881161d0800 (size 512):
+  comm "wpa_supplicant", pid 379, jiffies 4294749765
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+    00 00 00 00 00 00 00 00 f0 81 13 16 81 88 ff ff  ................
+  backtrace (crc c867fdb6):
+    kmemleak_alloc+0x89/0x90
+    __kmalloc_noprof+0x2fd/0x410
+    cfg80211_scan+0x133/0x730
+    nl80211_trigger_scan+0xc69/0x1cc0
+    genl_family_rcv_msg_doit+0x204/0x2f0
+    genl_rcv_msg+0x431/0x6b0
+    netlink_rcv_skb+0x143/0x3f0
+    genl_rcv+0x27/0x40
+    netlink_unicast+0x4f6/0x820
+    netlink_sendmsg+0x797/0xce0
+    __sock_sendmsg+0xc4/0x160
+    ____sys_sendmsg+0x5e4/0x890
+    ___sys_sendmsg+0xf8/0x180
+    __sys_sendmsg+0x136/0x1e0
+    __x64_sys_sendmsg+0x76/0xc0
+    x64_sys_call+0x13f0/0x17d0
+
+Found by Linux Verification Center (linuxtesting.org).
+
+Fixes: c8cb5b854b40 ("nl80211/cfg80211: support 6 GHz scanning")
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Link: https://patch.msgid.link/20260601094157.92703-1-pchelkin@ispras.ru
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/scan.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/net/wireless/scan.c b/net/wireless/scan.c
+index 4a1cdfc3221ca4..199c63de01457a 100644
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -1071,6 +1071,7 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)
+       struct cfg80211_scan_request_int *request;
+       struct cfg80211_scan_request_int *rdev_req = rdev->scan_req;
+       u32 n_channels = 0, idx, i;
++      int err;
+       if (!(rdev->wiphy.flags & WIPHY_FLAG_SPLIT_SCAN_6GHZ)) {
+               rdev_req->req.first_part = true;
+@@ -1101,8 +1102,14 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)
+       rdev_req->req.scan_6ghz = false;
+       rdev_req->req.first_part = true;
++      err = rdev_scan(rdev, request);
++      if (err) {
++              kfree(request);
++              return err;
++      }
++
+       rdev->int_scan_req = request;
+-      return rdev_scan(rdev, request);
++      return 0;
+ }
+ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
+-- 
+2.53.0
+
diff --git a/queue-6.18/wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch b/queue-6.18/wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch
new file mode 100644 (file)
index 0000000..31accf2
--- /dev/null
@@ -0,0 +1,45 @@
+From 1aee8ce3f32a35ba2cfaa3002964756929e5a3aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 08:57:05 +0300
+Subject: wifi: iwlwifi: mvm: don't support the reset handshake for old
+ firmwares
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+[ Upstream commit 0eaa1f245ac03ed0c6394159360532726f666811 ]
+
+-77.ucode doesn't contain the fixes for this flow it seems.
+Don't use the firmware reset handshake even if the firmware claims
+support for it.
+
+Fixes: 906d4eb84408 ("iwlwifi: support firmware reset handshake")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220600
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Reviewed-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20260529085453.9307b81d9b02.I21bba9e649f4cd0e35d3ea6cd97a03258be5832f@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+index 5ebd046371f50d..8e6913c7712f09 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+@@ -1416,6 +1416,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
+               fw_has_capa(&mvm->fw->ucode_capa,
+                           IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);
++      /* Those firmware versions claim to support the fw_reset_handshake
++       * but they are buggy.
++       */
++      if (IWL_UCODE_MAJOR(mvm->fw->ucode_ver) <= 77)
++              trans->conf.fw_reset_handshake = false;
++
+       trans->conf.queue_alloc_cmd_ver =
+               iwl_fw_lookup_cmd_ver(mvm->fw,
+                                     WIDE_ID(DATA_PATH_GROUP,
+-- 
+2.53.0
+
diff --git a/queue-6.18/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch b/queue-6.18/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch
new file mode 100644 (file)
index 0000000..fadb3fe
--- /dev/null
@@ -0,0 +1,61 @@
+From 13b91167008bcdbf88a5bf11f440ac2e5e80f157 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 06:47:21 +0530
+Subject: wifi: mac80211: limit injected antenna index in
+ ieee80211_parse_tx_radiotap
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 6c0cf89f36ac0c0fd8687a4ccdce2efb23a9c663 ]
+
+When parsing the radiotap header of an injected frame,
+ieee80211_parse_tx_radiotap() uses the IEEE80211_RADIOTAP_ANTENNA value
+directly as a shift count:
+
+       info->control.antennas |= BIT(*iterator.this_arg);
+
+*iterator.this_arg is an 8-bit value taken straight from the frame
+supplied by userspace, so BIT() can be asked to shift by up to 255. That
+is undefined behaviour on the unsigned long and is reported by UBSAN:
+
+  UBSAN: shift-out-of-bounds in net/mac80211/tx.c:2174:30
+  shift exponent 235 is too large for 64-bit type 'unsigned long'
+  Call Trace:
+   ieee80211_parse_tx_radiotap+0xadb/0x1950 net/mac80211/tx.c:2174
+   ieee80211_monitor_start_xmit+0xb1f/0x1250 net/mac80211/tx.c:2451
+   ...
+   packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3109
+
+info->control.antennas is a 2-bit bitmap (u8 antennas:2), so only antenna
+indices 0 and 1 can ever be represented. Ignore any larger value instead
+of shifting out of bounds.
+
+Reported-by: syzbot+8e0622f6d9446420271f@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8e0622f6d9446420271f
+Fixes: ef246a1480cc ("wifi: mac80211: support antenna control in injection")
+Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
+Link: https://patch.msgid.link/20260531011721.102941-1-kartikey406@gmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/tx.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 2f830001b0cd6d..98f0a275b60c3a 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -2169,7 +2169,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
+               case IEEE80211_RADIOTAP_ANTENNA:
+                       /* this can appear multiple times, keep a bitmap */
+-                      info->control.antennas |= BIT(*iterator.this_arg);
++                      /* control.antennas is only a 2-bit bitmap */
++                      if (*iterator.this_arg < 2)
++                              info->control.antennas |= BIT(*iterator.this_arg);
+                       break;
+               case IEEE80211_RADIOTAP_DATA_RETRIES:
+-- 
+2.53.0
+
diff --git a/queue-6.18/xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch b/queue-6.18/xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch
new file mode 100644 (file)
index 0000000..e014e1e
--- /dev/null
@@ -0,0 +1,73 @@
+From 1a07021e7974e804927ab6d0c8b8b36ccf1c60f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 May 2026 12:26:30 +0800
+Subject: xsk: cache csum_start/csum_offset to fix TOCTOU in xsk_skb_metadata()
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 22ba97ea9cc1f63a0d0244fae38057ed452b6ac7 ]
+
+The TX metadata area resides in the UMEM buffer which is memory-mapped
+and concurrently writable by userspace. In xsk_skb_metadata(),
+csum_start and csum_offset are read from shared memory for bounds
+validation, then read again for skb assignment. A malicious userspace
+application can race to overwrite these values between the two reads,
+bypassing the bounds check and causing out-of-bounds memory access
+during checksum computation in the transmit path.
+
+Fix this by reading csum_start and csum_offset into local variables
+once, then using the local copies for both validation and assignment.
+
+Note that other metadata fields (flags, launch_time) and the cached
+csum fields may be mutually inconsistent due to concurrent userspace
+writes, but this is benign: the only security-critical invariant is
+that each field's validated value is the same one used, which local
+caching guarantees.
+
+Closes: https://lore.kernel.org/all/20260503200927.73EA1C2BCB4@smtp.kernel.org/
+Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Fixes: 48eb03dd2630 ("xsk: Add TX timestamp and TX checksum offload support")
+Link: https://patch.msgid.link/20260530042630.80626-1-kerneljasonxing@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xsk.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 259ad9a3abcc42..9e0a486d54fb33 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -685,6 +685,7 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+                           u32 hr)
+ {
+       struct xsk_tx_metadata *meta = NULL;
++      u16 csum_start, csum_offset;
+       if (unlikely(pool->tx_metadata_len == 0))
+               return -EINVAL;
+@@ -694,13 +695,15 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+               return -EINVAL;
+       if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) {
+-              if (unlikely(meta->request.csum_start +
+-                           meta->request.csum_offset +
++              csum_start = READ_ONCE(meta->request.csum_start);
++              csum_offset = READ_ONCE(meta->request.csum_offset);
++
++              if (unlikely(csum_start + csum_offset +
+                            sizeof(__sum16) > desc->len))
+                       return -EINVAL;
+-              skb->csum_start = hr + meta->request.csum_start;
+-              skb->csum_offset = meta->request.csum_offset;
++              skb->csum_start = hr + csum_start;
++              skb->csum_offset = csum_offset;
+               skb->ip_summed = CHECKSUM_PARTIAL;
+               if (unlikely(pool->tx_sw_csum)) {
+-- 
+2.53.0
+
diff --git a/queue-6.6/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-6.6/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..fdeda97
--- /dev/null
@@ -0,0 +1,67 @@
+From 5682355411236e1cef8ba3886b10cef19c075d8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index e116d308a8df6d..37eaff3f7b6940 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch b/queue-6.6/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
new file mode 100644 (file)
index 0000000..97ac696
--- /dev/null
@@ -0,0 +1,71 @@
+From 6050dac57415a917605ae0d3141de360b0c286e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 17:39:53 +0800
+Subject: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame()
+ extension handling
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+[ Upstream commit 72b8deccff17a7644e0367e1aaf1a36cfb014324 ]
+
+In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
+BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:
+
+1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
+   performs a native-endian read. The BNEP protocol specifies this field
+   in big-endian (network byte order), and the same file correctly uses
+   get_unaligned_be16() for the identical fields in
+   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().
+
+2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
+   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
+   entry), the filter extension length field already represents the total
+   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
+   which reads the same field as a byte count and divides by 4 to get
+   the number of filter entries.
+
+   The bogus * 2 means skb_pull advances twice as far as it should,
+   either dropping valid data from the next header or causing the pull
+   to fail entirely when the doubled length exceeds the remaining skb.
+
+Fix by splitting the pull into two steps: first use skb_pull_data() to
+safely pull and validate the 3-byte fixed header (ctrl type + length),
+then pull the variable-length data using the properly decoded length.
+
+Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index e125afe573fcf2..9d804b08de88e0 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+                               goto badframe;
+                       break;
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET:
+-                      /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+-                      if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
++              case BNEP_FILTER_NET_TYPE_SET: {
++                      u8 *hdr;
++
++                      /* Pull ctrl type (1 b) + len (2 b) */
++                      hdr = skb_pull_data(skb, 3);
++                      if (!hdr)
++                              goto badframe;
++                      /* Pull data (len bytes); length is big-endian */
++                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+                               goto badframe;
+                       break;
++              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-bnep-reject-short-frames-before-parsing.patch b/queue-6.6/bluetooth-bnep-reject-short-frames-before-parsing.patch
new file mode 100644 (file)
index 0000000..1731314
--- /dev/null
@@ -0,0 +1,170 @@
+From 8435ec5230ab97655b7182aaee9256f5414eb9aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 11:22:09 +0800
+Subject: Bluetooth: bnep: reject short frames before parsing
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 6770d3a8acdf9151769180cc3710346c4cfbe6f0 ]
+
+A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
+packet type byte immediately and, for control packets, reads the control
+opcode and setup UUID-size byte before proving that those bytes are
+present. bnep_rx_control() also dereferences the control opcode without
+rejecting an empty control payload.
+
+Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
+return gates each dereference. Split the control handler so the frame
+path can pass an opcode that has already been pulled, and keep the
+byte-buffer wrapper for extension control payloads.
+
+For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
+setup payload. struct bnep_setup_conn_req carries destination and source
+service UUIDs after that byte, each uuid_size bytes, so the parser now
+documents that tuple explicitly instead of leaving the pull length as an
+opaque multiplication.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
+The buggy address belongs to the object at ffff88800c0f7908 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 1-byte
+region [ffff88800c0f7908, ffff88800c0f7909)
+Read of size 1
+Call trace:
+  dump_stack_lvl+0xb3/0x140 (?:?)
+  print_address_description+0x57/0x3a0 (?:?)
+  bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
+  print_report+0xb9/0x2b0 (?:?)
+  __virt_addr_valid+0x1ba/0x3a0 (?:?)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  kasan_addr_to_slab+0x21/0x60 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
+  worker_thread+0x65c/0xe40 (?:?)
+  __kthread_parkme+0x184/0x230 (?:?)
+  kthread+0x35e/0x470 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  ret_from_fork+0x586/0x870 (?:?)
+  __switch_to+0x74f/0xdc0 (?:?)
+  ret_from_fork_asm+0x1a/0x30 (?:?)
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index 9d804b08de88e0..45d0f84652fc60 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
+       return 0;
+ }
+-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
++                             int len)
+ {
+-      u8  cmd = *(u8 *)data;
+       int err = 0;
+-      data++;
+-      len--;
+-
+       switch (cmd) {
+       case BNEP_CMD_NOT_UNDERSTOOD:
+       case BNEP_SETUP_CONN_RSP:
+@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+       return err;
+ }
++static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++{
++      if (len < 1)
++              return -EILSEQ;
++
++      return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
++}
++
+ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct bnep_ext_hdr *h;
+@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct net_device *dev = s->dev;
+       struct sk_buff *nskb;
++      u8 *data;
+       u8 type, ctrl_type;
+       dev->stats.rx_bytes += skb->len;
+-      type = *(u8 *) skb->data;
+-      skb_pull(skb, 1);
+-      ctrl_type = *(u8 *)skb->data;
++      data = skb_pull_data(skb, sizeof(type));
++      if (!data)
++              goto badframe;
++      type = *data;
+       if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
+               goto badframe;
+       if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
+-              if (bnep_rx_control(s, skb->data, skb->len) < 0) {
++              data = skb_pull_data(skb, sizeof(ctrl_type));
++              if (!data)
++                      goto badframe;
++              ctrl_type = *data;
++
++              if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
+                       dev->stats.tx_errors++;
+                       kfree_skb(skb);
+                       return 0;
+@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+               /* Verify and pull ctrl message since it's already processed */
+               switch (ctrl_type) {
+-              case BNEP_SETUP_CONN_REQ:
+-                      /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+-                      if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
++              case BNEP_SETUP_CONN_REQ: {
++                      u8 uuid_size;
++
++                      /* Pull uuid_size and the dst/src service UUIDs. */
++                      data = skb_pull_data(skb, sizeof(uuid_size));
++                      if (!data)
++                              goto badframe;
++                      uuid_size = *data;
++                      if (!skb_pull(skb, uuid_size + uuid_size))
+                               goto badframe;
+                       break;
++              }
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET: {
+-                      u8 *hdr;
+-
+-                      /* Pull ctrl type (1 b) + len (2 b) */
+-                      hdr = skb_pull_data(skb, 3);
+-                      if (!hdr)
++              case BNEP_FILTER_NET_TYPE_SET:
++                      /* Pull: len (2 b), data (len bytes) */
++                      data = skb_pull_data(skb, sizeof(u16));
++                      if (!data)
+                               goto badframe;
+-                      /* Pull data (len bytes); length is big-endian */
+-                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
++                      if (!skb_pull(skb, get_unaligned_be16(data)))
+                               goto badframe;
+                       break;
+-              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch b/queue-6.6/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
new file mode 100644 (file)
index 0000000..08781db
--- /dev/null
@@ -0,0 +1,58 @@
+From 92509b57f8fcaaaebebba4ee24070e73ed0dfcf1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 08:54:26 +0530
+Subject: Bluetooth: fix memory leak in error path of hci_alloc_dev()
+
+From: Bharath Reddy <kbreddy.rpbc@gmail.com>
+
+[ Upstream commit 37b3009bf5976e8ab77c8b9a9bc3bbd7ff49e37f ]
+
+Early failures in Bluetooth HCI UART configuration leak SRCU percpu
+memory.
+
+When device initialization fails before hci_register_dev() completes,
+the HCI_UNREGISTER flag is never set. As a result, when the device
+reference count reaches zero, bt_host_release() evaluates this flag as
+false and falls back to a direct kfree(hdev).
+
+Because hci_release_dev() is bypassed, the SRCU struct initialized
+early in hci_alloc_dev() is never cleaned up, resulting in a leak of
+percpu memory.
+
+Fix the leak by explicitly calling cleanup_srcu_struct() in the
+fallback (unregistered) branch of bt_host_release() before freeing
+the device.
+
+Reported-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=535ecc844591e50588a5
+Tested-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Fixes: 1d6123102e9f ("Bluetooth: hci_core: Fix use-after-free in vhci_flush()")
+Signed-off-by: Bharath Reddy <kbreddy.rpbc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sysfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
+index 4b54dbbf0729a3..60350c6723cb76 100644
+--- a/net/bluetooth/hci_sysfs.c
++++ b/net/bluetooth/hci_sysfs.c
+@@ -83,10 +83,12 @@ static void bt_host_release(struct device *dev)
+ {
+       struct hci_dev *hdev = to_hci_dev(dev);
+-      if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
++      if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_release_dev(hdev);
+-      else
++      } else {
++              cleanup_srcu_struct(&hdev->srcu);
+               kfree(hdev);
++      }
+       module_put(THIS_MODULE);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-mgmt-fix-backward-compatibility-with-users.patch b/queue-6.6/bluetooth-mgmt-fix-backward-compatibility-with-users.patch
new file mode 100644 (file)
index 0000000..1d1d950
--- /dev/null
@@ -0,0 +1,43 @@
+From bcb33b4138da75b06e790ecde0c60bedfab75d79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:48:34 -0400
+Subject: Bluetooth: MGMT: Fix backward compatibility with userspace
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 149324fc762c2a7acef9c26790566f81f475e51f ]
+
+bluetoothd has a bug with makes it send extra bytes as part of
+MGMT_OP_ADD_EXT_ADV_DATA which are now being checked to be the
+exact the expected length, relax this so only when the expected
+length is greater than the data length to cause an error since
+that would result in accessing invalid memory, otherwise just
+ignore the extra bytes.
+
+Link: https://lore.kernel.org/linux-bluetooth/20260602204749.210857-1-luiz.dentz@gmail.com/T/#u
+Fixes: d3f7d17960ed ("Bluetooth: MGMT: validate Add Extended Advertising Data length")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 7b86e287b12d64..88f44cb36e241e 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -9144,8 +9144,9 @@ static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data,
+       BT_DBG("%s", hdev->name);
+-      expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len);
+-      if (expected_len != data_len)
++      expected_len = struct_size(cp, data, cp->adv_data_len +
++                                 cp->scan_rsp_len);
++      if (expected_len > data_len)
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
+                                      MGMT_STATUS_INVALID_PARAMS);
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-6.6/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..1886b86
--- /dev/null
@@ -0,0 +1,73 @@
+From 0b303417a25df3b775bd2dbbae0cac87de5620ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 4271fba3245ce1..7b86e287b12d64 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -8667,6 +8667,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -8683,12 +8689,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-6.6/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..8b52d0d
--- /dev/null
@@ -0,0 +1,126 @@
+From 8b7dc9c0c18f5cb26721dda836f9ca4707889105 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index bc2b22c2b3aec7..d72cdcd2e2bb11 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -941,6 +951,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -954,6 +965,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -981,9 +997,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       release_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch b/queue-6.6/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
new file mode 100644 (file)
index 0000000..336a6c1
--- /dev/null
@@ -0,0 +1,167 @@
+From aff357d33d7279eb136d3c7628ffb99c31b8d981 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:04:43 +0900
+Subject: Bluetooth: RFCOMM: validate skb length in MCC handlers
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 23882b828c3c8c51d0c946446a396b10abb3b16b ]
+
+The RFCOMM MCC handlers cast skb->data to protocol-specific structs
+without validating skb->len first. A malicious remote device can send
+truncated MCC frames and trigger out-of-bounds reads in these handlers.
+
+Fix this by using skb_pull_data() to validate and access the required
+data before dereferencing it.
+
+rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
+1-byte RPN requests. Handle this by validating only the DLCI byte first,
+and validating the full struct only when len > 1.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
+ 1 file changed, 49 insertions(+), 18 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
+index 1d34d849703329..07971e918e5b60 100644
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -1431,10 +1431,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
+ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_pn *pn = (void *) skb->data;
++      struct rfcomm_pn *pn;
+       struct rfcomm_dlc *d;
+-      u8 dlci = pn->dlci;
++      u8 dlci;
++
++      pn = skb_pull_data(skb, sizeof(*pn));
++      if (!pn)
++              return -EILSEQ;
++      dlci = pn->dlci;
+       BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
+       if (!dlci)
+@@ -1483,8 +1488,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
+ {
+-      struct rfcomm_rpn *rpn = (void *) skb->data;
+-      u8 dlci = __get_dlci(rpn->dlci);
++      struct rfcomm_rpn *rpn;
++      u8 dlci;
+       u8 bit_rate  = 0;
+       u8 data_bits = 0;
+@@ -1495,15 +1500,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+       u8 xoff_char = 0;
+       u16 rpn_mask = RFCOMM_RPN_PM_ALL;
+-      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+-              dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+-              rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++      if (len == 1) {
++              rpn = skb_pull_data(skb, 1);
++              if (!rpn)
++                      return -EILSEQ;
+-      if (!cr)
+-              return 0;
++              dlci = __get_dlci(rpn->dlci);
++
++              if (!cr)
++                      return 0;
+-      if (len == 1) {
+-              /* This is a request, return default (according to ETSI TS 07.10) settings */
+               bit_rate  = RFCOMM_RPN_BR_9600;
+               data_bits = RFCOMM_RPN_DATA_8;
+               stop_bits = RFCOMM_RPN_STOP_1;
+@@ -1514,6 +1520,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+               goto rpn_out;
+       }
++      rpn = skb_pull_data(skb, sizeof(*rpn));
++      if (!rpn)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rpn->dlci);
++
++      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
++             dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
++             rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++
++      if (!cr)
++              return 0;
++
+       /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+        * no parity, no flow control lines, normal XON/XOFF chars */
+@@ -1589,9 +1608,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_rls *rls = (void *) skb->data;
+-      u8 dlci = __get_dlci(rls->dlci);
++      struct rfcomm_rls *rls;
++      u8 dlci;
++      rls = skb_pull_data(skb, sizeof(*rls));
++      if (!rls)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rls->dlci);
+       BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+       if (!cr)
+@@ -1608,10 +1632,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_msc *msc = (void *) skb->data;
++      struct rfcomm_msc *msc;
+       struct rfcomm_dlc *d;
+-      u8 dlci = __get_dlci(msc->dlci);
++      u8 dlci;
++
++      msc = skb_pull_data(skb, sizeof(*msc));
++      if (!msc)
++              return -EILSEQ;
++      dlci = __get_dlci(msc->dlci);
+       BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
+       d = rfcomm_dlc_get(s, dlci);
+@@ -1644,17 +1673,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
+ {
+-      struct rfcomm_mcc *mcc = (void *) skb->data;
++      struct rfcomm_mcc *mcc;
+       u8 type, cr, len;
++      mcc = skb_pull_data(skb, sizeof(*mcc));
++      if (!mcc)
++              return -EILSEQ;
++
+       cr   = __test_cr(mcc->type);
+       type = __get_mcc_type(mcc->type);
+       len  = __get_mcc_len(mcc->len);
+       BT_DBG("%p type 0x%x cr %d", s, type, cr);
+-      skb_pull(skb, 2);
+-
+       switch (type) {
+       case RFCOMM_PN:
+               rfcomm_recv_pn(s, cr, skb);
+-- 
+2.53.0
+
diff --git a/queue-6.6/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-6.6/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..280eb49
--- /dev/null
@@ -0,0 +1,71 @@
+From 4ba915ebc5828776fce9888dea3588cc1b22bd85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index 1566e040f7aac7..c4bc5016840c25 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1590,18 +1590,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-6.6/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-6.6/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..6bb75db
--- /dev/null
@@ -0,0 +1,53 @@
+From b7ab0a61684e6f56b73759d9fb7fa3188c6659eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index 47852b9dd5eaa2..d2a89a99bd71cf 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -166,6 +166,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-6.6/hsr-remove-warn_once-in-hsr_addr_is_self.patch b/queue-6.6/hsr-remove-warn_once-in-hsr_addr_is_self.patch
new file mode 100644 (file)
index 0000000..ddd8cb7
--- /dev/null
@@ -0,0 +1,109 @@
+From 0a275e2ff3230e09fd153d2472c9b2fbc4e86176 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 May 2026 06:42:58 +0000
+Subject: hsr: Remove WARN_ONCE() in hsr_addr_is_self().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit afd0f17ca46258cec3a5cc48b8df9327fe772490 ]
+
+syzbot reported the warning [0] in hsr_addr_is_self(),
+whose assumption is simply wrong.
+
+hsr->self_node is cleared in hsr_del_self_node(), which
+is called from hsr_dellink().
+
+Since dev->rtnl_link_ops->dellink() is called before
+unregister_netdevice_many(), there is a window when
+user can find the device but without hsr->self_node.
+
+Let's remove WARN_ONCE() in hsr_addr_is_self().
+
+[0]:
+HSR: No self node
+WARNING: net/hsr/hsr_framereg.c:39 at hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39, CPU#0: syz.4.16848/17220
+Modules linked in:
+CPU: 0 UID: 0 PID: 17220 Comm: syz.4.16848 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39
+Code: 33 2f 41 0f b7 dd 89 ee 09 de 31 ff e8 c8 b4 c6 f6 09 dd 74 54 e8 0f b0 c6 f6 31 ed eb 53 e8 06 b0 c6 f6 48 8d 3d 2f 50 9c 04 <67> 48 0f b9 3a 31 ed eb 42 e8 c1 13 1f 00 89 c5 31 ff 89 c6 e8 96
+RSP: 0018:ffffc900041c70e0 EFLAGS: 00010283
+RAX: ffffffff8afdc6ca RBX: ffffffff8afdc4e6 RCX: 0000000000080000
+RDX: ffffc90010493000 RSI: 0000000000000948 RDI: ffffffff8f9a1700
+RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
+R10: ffffc900041c71e8 R11: fffff52000838e3f R12: dffffc0000000000
+R13: ffff888041f9e3c0 R14: ffff888086ee3802 R15: 0000000000000000
+FS:  00007f6fe985d6c0(0000) GS:ffff888126176000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f80bd437dac CR3: 0000000025096000 CR4: 00000000003526f0
+DR0: ffffffffffffffff DR1: 00000000000001f8 DR2: 0000000000000002
+DR3: ffffffffefffff15 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ check_local_dest net/hsr/hsr_forward.c:592 [inline]
+ fill_frame_info net/hsr/hsr_forward.c:728 [inline]
+ hsr_forward_skb+0xa11/0x2a80 net/hsr/hsr_forward.c:739
+ hsr_dev_xmit+0x253/0x370 net/hsr/hsr_device.c:236
+ __netdev_start_xmit include/linux/netdevice.h:5368 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5377 [inline]
+ xmit_one net/core/dev.c:3888 [inline]
+ dev_hard_start_xmit+0x2df/0x860 net/core/dev.c:3904
+ __dev_queue_xmit+0x1428/0x3900 net/core/dev.c:4870
+ neigh_output include/net/neighbour.h:556 [inline]
+ ip_finish_output2+0xcec/0x10b0 net/ipv4/ip_output.c:237
+ ip_send_skb net/ipv4/ip_output.c:1510 [inline]
+ ip_push_pending_frames+0x8b/0x110 net/ipv4/ip_output.c:1530
+ raw_sendmsg+0x1547/0x1a50 net/ipv4/raw.c:659
+ sock_sendmsg_nosec net/socket.c:787 [inline]
+ __sock_sendmsg net/socket.c:802 [inline]
+ ____sys_sendmsg+0x7da/0x9c0 net/socket.c:2698
+ ___sys_sendmsg+0x2a5/0x360 net/socket.c:2752
+ __sys_sendmsg net/socket.c:2784 [inline]
+ __do_sys_sendmsg net/socket.c:2789 [inline]
+ __se_sys_sendmsg net/socket.c:2787 [inline]
+ __x64_sys_sendmsg+0x1c3/0x2a0 net/socket.c:2787
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f6feb62ce59
+Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f6fe985d028 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f6feb8a6090 RCX: 00007f6feb62ce59
+RDX: 0000000000000000 RSI: 0000200000000000 RDI: 0000000000000004
+RBP: 00007f6feb6c2d6f R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007f6feb8a6128 R14: 00007f6feb8a6090 R15: 00007ffcf01cc488
+ </TASK>
+
+Fixes: f266a683a480 ("net/hsr: Better frame dispatch")
+Reported-by: syzbot+652670cf249077eb498b@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1a861e.b111c304.35cd64.0016.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260530064300.340793-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_framereg.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index 26329db09210bb..ad07a3b1ac20f0 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -43,10 +43,8 @@ bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr)
+       rcu_read_lock();
+       sn = rcu_dereference(hsr->self_node);
+-      if (!sn) {
+-              WARN_ONCE(1, "HSR: No self node\n");
++      if (!sn)
+               goto out;
+-      }
+       if (ether_addr_equal(addr, sn->macaddress_A) ||
+           ether_addr_equal(addr, sn->macaddress_B))
+-- 
+2.53.0
+
diff --git a/queue-6.6/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-6.6/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..dede77a
--- /dev/null
@@ -0,0 +1,56 @@
+From 71d21c0421e4b8573e51c9ded4bb961c4bfbb796 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-6.6/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-6.6/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..ee3c8fc
--- /dev/null
@@ -0,0 +1,54 @@
+From 24e29da5ff91b6083fb6a95f7b35d467314dd3f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index d898e1523a453e..7a60bbf4bee3aa 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -530,6 +530,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.6/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch b/queue-6.6/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
new file mode 100644 (file)
index 0000000..a4d7443
--- /dev/null
@@ -0,0 +1,107 @@
+From 1bb28a2c0b24a60a2a573a9a1664c70a7b819c84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 13:18:11 +0300
+Subject: ipv6: mcast: Fix use-after-free when processing MLD queries
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ]
+
+When processing an MLD query, a pointer to the multicast group address
+is retrieved when initially parsing the packet. This pointer is later
+dereferenced without being reloaded despite the fact that the skb header
+might have been reallocated following the pskb_may_pull() calls, leading
+to a use-after-free [1].
+
+Fix by copying the multicast group address when the packet is initially
+parsed.
+
+[1]
+BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512)
+Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
+
+Workqueue: mld mld_query_work
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+print_address_description.constprop.0 (mm/kasan/report.c:378)
+print_report (mm/kasan/report.c:482)
+kasan_report (mm/kasan/report.c:595)
+__mld_query_work (net/ipv6/mcast.c:1512)
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+</TASK>
+
+[...]
+
+Freed by task 118:
+kasan_save_stack (mm/kasan/common.c:57)
+kasan_save_track (mm/kasan/common.c:78)
+kasan_save_free_info (mm/kasan/generic.c:584)
+__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
+kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566)
+pskb_expand_head (net/core/skbuff.c:2335)
+__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4))
+__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+
+Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Reviewed-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/mcast.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index 160b452f75e7d2..c52865e20a4114 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1392,9 +1392,9 @@ void igmp6_event_query(struct sk_buff *skb)
+ static void __mld_query_work(struct sk_buff *skb)
+ {
+       struct mld2_query *mlh2 = NULL;
+-      const struct in6_addr *group;
+       unsigned long max_delay;
+       struct inet6_dev *idev;
++      struct in6_addr group;
+       struct ifmcaddr6 *ma;
+       struct mld_msg *mld;
+       int group_type;
+@@ -1426,8 +1426,8 @@ static void __mld_query_work(struct sk_buff *skb)
+               goto kfree_skb;
+       mld = (struct mld_msg *)icmp6_hdr(skb);
+-      group = &mld->mld_mca;
+-      group_type = ipv6_addr_type(group);
++      group = mld->mld_mca;
++      group_type = ipv6_addr_type(&group);
+       if (group_type != IPV6_ADDR_ANY &&
+           !(group_type&IPV6_ADDR_MULTICAST))
+@@ -1477,7 +1477,7 @@ static void __mld_query_work(struct sk_buff *skb)
+               }
+       } else {
+               for_each_mc_mclock(idev, ma) {
+-                      if (!ipv6_addr_equal(group, &ma->mca_addr))
++                      if (!ipv6_addr_equal(&group, &ma->mca_addr))
+                               continue;
+                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                               /* gsquery <- gsquery && mark */
+-- 
+2.53.0
+
diff --git a/queue-6.6/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-6.6/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..e2eef38
--- /dev/null
@@ -0,0 +1,127 @@
+From ee96bb7f20fe494e769042f1fbac083926bbac7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index ff406ef4fd4aab..d70268cf1af82e 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1506,8 +1506,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 25f586fab2bcc9..27b7552b1e2481 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1496,7 +1496,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1558,9 +1558,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1568,6 +1567,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1624,7 +1627,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index d4903723be7e90..49b2e5d2b2c837 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch b/queue-6.6/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
new file mode 100644 (file)
index 0000000..d40fc75
--- /dev/null
@@ -0,0 +1,75 @@
+From e20bb720112d604a637b91bf2b42a93a8cd0232f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 00:00:00 +0000
+Subject: ksmbd: fix NULL-deref of opinfo->conn in oplock/lease break notifiers
+
+From: Gil Portnoy <dddhkts1@gmail.com>
+
+[ Upstream commit b003086d76968298f22e7cf62239833b5a3a06b1 ]
+
+smb2_oplock_break_noti() and smb2_lease_break_noti() read opinfo->conn
+into a local with neither READ_ONCE() nor a NULL check.  Both run from
+oplock_break() after opinfo_get_list() has dropped ci->m_lock, so a
+concurrent SMB2 LOGOFF (session_fd_check()) can set op->conn = NULL
+under ci->m_lock within that window.  ksmbd_conn_r_count_inc(conn) then
+writes through NULL at offset 0xc4 -- a remotely triggerable oops.
+
+Guard both reads the way compare_guid_key() already does: read
+opinfo->conn with READ_ONCE() and return early if it is NULL, before
+allocating the work struct so nothing leaks.  A NULL conn means the
+client is gone and the break is moot, so return 0; oplock_break() treats
+that as success and runs the normal teardown.
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Assisted-by: Henry (Claude):claude-opus-4
+Signed-off-by: Gil Portnoy <dddhkts1@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/oplock.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index 5302c30a4a91d7..bba17ea84023e2 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -714,11 +714,16 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
+  */
+ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct oplock_break_info *br_info;
+       int ret = 0;
+-      struct ksmbd_work *work = ksmbd_alloc_work_struct();
++      struct ksmbd_work *work;
++
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++      work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+@@ -818,11 +823,15 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
+  */
+ static int smb2_lease_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct ksmbd_work *work;
+       struct lease_break_info *br_info;
+       struct lease *lease = opinfo->o_lease;
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++
+       work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-6.6/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..01cd60b
--- /dev/null
@@ -0,0 +1,79 @@
+From c14972b8c3909516081c00eaac66c9a40acdeec3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index eafc21ecc287d9..a58e697e182a8f 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -702,6 +702,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -752,6 +758,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-annotate-sk-sk_write_space-for-udp-sockmap.patch b/queue-6.6/net-annotate-sk-sk_write_space-for-udp-sockmap.patch
new file mode 100644 (file)
index 0000000..15f374b
--- /dev/null
@@ -0,0 +1,60 @@
+From bee60c5535c91e722b8f498e113b0b5a159ebdd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:39:23 +0000
+Subject: net: Annotate sk->sk_write_space() for UDP SOCKMAP.
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit b748765019fe9e9234660327090fc1a9665cdbdd ]
+
+UDP TX skb->destructor() is sock_wfree(), and UDP holds lock_sock()
+only for UDP_CORK / MSG_MORE sendmsg().
+
+Otherwise, sk->sk_write_space() may be read locklessly while SOCKMAP
+rewrites sk->sk_write_space().
+
+Let's use WRITE_ONCE() and READ_ONCE() for sk->sk_write_space().
+
+Note that the write side is annotated by commit 2ef2b20cf4e0
+("net: annotate data-races around sk->sk_{data_ready,write_space}").
+
+Fixes: 7b98cd42b049 ("bpf: sockmap: Add UDP support")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://patch.msgid.link/20260529193941.3897256-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 8e4c87a39dc87b..267f771dda1cc2 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2499,8 +2499,12 @@ void sock_wfree(struct sk_buff *skb)
+       bool free;
+       if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
++              void (*sk_write_space)(struct sock *sk);
++
++              sk_write_space = READ_ONCE(sk->sk_write_space);
++
+               if (sock_flag(sk, SOCK_RCU_FREE) &&
+-                  sk->sk_write_space == sock_def_write_space) {
++                  sk_write_space == sock_def_write_space) {
+                       rcu_read_lock();
+                       free = refcount_sub_and_test(len, &sk->sk_wmem_alloc);
+                       sock_def_write_space_wfree(sk);
+@@ -2515,7 +2519,7 @@ void sock_wfree(struct sk_buff *skb)
+                * after sk_write_space() call
+                */
+               WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
+-              sk->sk_write_space(sk);
++              sk_write_space(sk);
+               len = 1;
+       }
+       /*
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch b/queue-6.6/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
new file mode 100644 (file)
index 0000000..0c62c45
--- /dev/null
@@ -0,0 +1,48 @@
+From 267525423e65517c9f4cc007c0334a89c0a68516 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:21:05 +0200
+Subject: net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst
+ teardown
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit 80df409e1a483676826a6c66e693dba6ac507751 ]
+
+mtk_free_dev() calls metadata_dst_free() which frees the metadata_dst
+with kfree() immediately, bypassing the RCU grace period.
+In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
+the skb to the metadata_dst. This function requires RCU read-side
+protection and the dst must remain valid until all RCU readers complete.
+Since metadata_dst_free() calls kfree() directly, a use-after-free can
+occur if any skb still holds a noref pointer to the dst when the driver
+tears it down.
+Replace metadata_dst_free() with dst_release() which properly goes
+through the refcount path: when the refcount drops to zero, it schedules
+the actual free via call_rcu_hurry(), ensuring all RCU readers have
+completed before the memory is freed.
+
+Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-2-3aaa99d83351@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index 74cb96dbff9ee4..6de783fe116ce8 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -4246,7 +4246,7 @@ static int mtk_free_dev(struct mtk_eth *eth)
+       for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
+               if (!eth->dsa_meta[i])
+                       break;
+-              metadata_dst_free(eth->dsa_meta[i]);
++              dst_release(&eth->dsa_meta[i]->dst);
+       }
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch b/queue-6.6/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
new file mode 100644 (file)
index 0000000..a4445ac
--- /dev/null
@@ -0,0 +1,62 @@
+From c836fb663d2b8fb548ee5339c8c9cd28ca379d57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 06:18:57 +0000
+Subject: net: fec: fix pinctrl default state restore order on resume
+
+From: Tapio Reijonen <tapio.reijonen@vaisala.com>
+
+[ Upstream commit b455410146bf723c7ebcb49ecd5becc0d6611482 ]
+
+In fec_resume(), fec_enet_clk_enable() is called before
+pinctrl_pm_select_default_state() in the non-WoL path, inverting the
+ordering used in fec_suspend() which correctly switches to the sleep
+pinctrl state before disabling clocks.
+
+For PHYs with the PHY_RST_AFTER_CLK_EN flag (e.g. TI DP83848 or
+SMSC LAN87xx), fec_enet_clk_enable() triggers a hardware reset pulse
+via the phy-reset GPIO. With the GPIO pin still in sleep pinctrl state
+at that point, the GPIO write has no physical effect and the PHY never
+receives the required reset after clock enable, leading to unreliable
+link establishment after system resume.
+
+Fix by restoring the default pinctrl state before enabling clocks,
+making resume the proper mirror of suspend. The call is made
+unconditionally: fec_suspend() only switches to the sleep pinctrl state
+on the non-WoL path and leaves the pins in the default state when WoL
+is enabled, so on a WoL resume the device is already in the default
+state and pinctrl_pm_select_default_state() is a no-op.
+
+Fixes: de40ed31b3c5 ("net: fec: add Wake-on-LAN support")
+Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20260529-b4-fec-resume-pinctrl-order-v3-1-6eda0f592fca@vaisala.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 7efe4e81cf320b..49297b83c3fdb8 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -4734,6 +4734,7 @@ static int __maybe_unused fec_resume(struct device *dev)
+               if (fep->rpm_active)
+                       pm_runtime_force_resume(dev);
++              pinctrl_pm_select_default_state(&fep->pdev->dev);
+               ret = fec_enet_clk_enable(ndev, true);
+               if (ret) {
+                       rtnl_unlock();
+@@ -4750,8 +4751,6 @@ static int __maybe_unused fec_resume(struct device *dev)
+                       val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
+                       writel(val, fep->hwp + FEC_ECNTRL);
+                       fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
+-              } else {
+-                      pinctrl_pm_select_default_state(&fep->pdev->dev);
+               }
+               fec_restart(ndev);
+               netif_tx_lock_bh(ndev);
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-6.6/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..b2b2d1c
--- /dev/null
@@ -0,0 +1,58 @@
+From 8bea8d1f5e6b6c0897f179772065cf82cd0d5ab7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index ab24b21fbb4938..d263f8ffdceec3 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -452,7 +452,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-6.6/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..7442fb1
--- /dev/null
@@ -0,0 +1,99 @@
+From c77bf7e98c1342279812ecdb4562647dc56193b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 8910928b38498b..50abc227f6f160 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -1255,6 +1255,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -1294,6 +1324,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       eth_hw_addr_set(netdev, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index b6c83c68241e63..f1d346db85ea04 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -180,6 +180,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-6.6/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-6.6/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..6900514
--- /dev/null
@@ -0,0 +1,106 @@
+From f353969d2745945d7e590ff6a1e37bc58c999394 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index 8db6994c90eec1..56f49351fd5177 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -42,6 +42,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *user_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index e509ac28c49299..bed04ae3003c43 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -112,11 +112,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -129,7 +124,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void offload_action_hw_count_set(struct tc_action *act,
+-- 
+2.53.0
+
diff --git a/queue-6.6/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-6.6/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..a8d0246
--- /dev/null
@@ -0,0 +1,58 @@
+From fa0486205d37ca40722a4c3d6a34d876f4ee0778 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-6.6/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-6.6/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..ec8be24
--- /dev/null
@@ -0,0 +1,50 @@
+From 8883579051e59faefa0e33682fbe0422682d7e75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index 5703846bea3b69..0f50ea92ced9df 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -208,7 +208,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -222,7 +222,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-6.6/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch b/queue-6.6/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
new file mode 100644 (file)
index 0000000..5ba8251
--- /dev/null
@@ -0,0 +1,96 @@
+From b9853b57bbf89b54d15dbc65d321de2a56f8a43b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:09:19 +0800
+Subject: netfilter: nft_ct: bail out on template ct in get eval
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 3027ecbdb5fdf9200251c21d4818e4c447ef78e1 ]
+
+I noticed this issue while looking at a historic syzbot report [1].
+
+A rule like the one below is enough to trigger the bug:
+
+    table ip t {
+        chain pre {
+            type filter hook prerouting priority raw;
+            ct zone set 1
+            ct original saddr 1.2.3.4 accept
+        }
+    }
+
+The first expression attaches a per-cpu template ct via
+nft_ct_set_zone_eval() (nf_ct_tmpl_alloc -> kzalloc, tuple is all
+zero, nf_ct_l3num(ct) == 0). The next expression then calls
+nft_ct_get_eval() on the same skb, treats the template as a real ct
+and hits the 16-byte memcpy path. With dreg at NFT_REG32_15 this
+overflows past struct nft_regs on the kernel stack; with smaller
+dreg values it silently clobbers adjacent registers.
+
+Reject template ct at the eval entry and in nft_ct_get_fast_eval(),
+mirroring the check nft_ct_set_eval() already has. Additionally,
+bound the address copy in NFT_CT_SRC / NFT_CT_DST by priv->len
+instead of by nf_ct_l3num(ct): nf_ct_get_tuple() zeroes the tuple
+before pkt_to_tuple() fills in only the protocol-relevant leading
+bytes, so the trailing bytes of tuple->{src,dst}.u3.all are
+well-defined zero. priv->len is validated at rule load, so the
+copy size is now bounded by the destination register rather than
+by an untrusted field on the conntrack.
+
+[1]: https://syzkaller.appspot.com/bug?id=389cf09cb72926114fce90dc85a2c3231dcb647c
+
+Fixes: 45d9bcda21f4 ("netfilter: nf_tables: validate len in nft_validate_data_load()")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+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>
+---
+ net/netfilter/nft_ct.c      | 8 +++-----
+ net/netfilter/nft_ct_fast.c | 2 +-
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 83c963e668ffe0..e83aa87a348e7d 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -78,7 +78,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (ct == NULL)
++      if (!ct || nf_ct_is_template(ct))
+               goto err;
+       switch (priv->key) {
+@@ -180,12 +180,10 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+       tuple = &ct->tuplehash[priv->dir].tuple;
+       switch (priv->key) {
+       case NFT_CT_SRC:
+-              memcpy(dest, tuple->src.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->src.u3.all, priv->len);
+               return;
+       case NFT_CT_DST:
+-              memcpy(dest, tuple->dst.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->dst.u3.all, priv->len);
+               return;
+       case NFT_CT_PROTO_SRC:
+               nft_reg_store16(dest, (__force u16)tuple->src.u.all);
+diff --git a/net/netfilter/nft_ct_fast.c b/net/netfilter/nft_ct_fast.c
+index e684c8a9184877..ecf7b3a404be26 100644
+--- a/net/netfilter/nft_ct_fast.c
++++ b/net/netfilter/nft_ct_fast.c
+@@ -30,7 +30,7 @@ void nft_ct_get_fast_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (!ct) {
++      if (!ct || nf_ct_is_template(ct)) {
+               regs->verdict.code = NFT_BREAK;
+               return;
+       }
+-- 
+2.53.0
+
diff --git a/queue-6.6/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-6.6/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..1f2488c
--- /dev/null
@@ -0,0 +1,113 @@
+From 1c347da9d6cf2a53112f096b961599ebede38fc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index f5a52075691faa..500a90311ed505 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -21,6 +21,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -768,26 +770,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1192,27 +1199,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-6.6/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-6.6/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..04e36e1
--- /dev/null
@@ -0,0 +1,41 @@
+From fbed5eccdaae33b9f4780e806a94db504d865da3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-6.6/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch b/queue-6.6/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
new file mode 100644 (file)
index 0000000..3ba3606
--- /dev/null
@@ -0,0 +1,119 @@
+From ade889b3d4b22a008d2bd39504bcf2d2603d786c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 10:28:53 +0530
+Subject: octeontx2-af: npc: Fix CPT channel mask in npc_install_flow
+
+From: Nithin Dabilpuram <ndabilpuram@marvell.com>
+
+[ Upstream commit 1d31eb27e570daa04f5373345f9ac98c95863be9 ]
+
+Use the CPT-aware NIX channel mask in the npc_install_flow path so that
+when the host PF installs steering rules in kernel for a VF used from
+userspace (e.g. DPDK), MCAM entries see the same channel mask semantics as
+other RX paths.
+
+Fixes: 56bcef528bd8 ("octeontx2-af: Use npc_install_flow API for promisc and broadcast entries")
+Cc: Naveen Mamindlapalli <naveenm@marvell.com>
+Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
+Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
+Link: https://patch.msgid.link/20260602045853.1558530-1-rkannoth@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |  1 +
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   | 32 +++++++++----------
+ .../marvell/octeontx2/af/rvu_npc_fs.c         |  2 +-
+ 3 files changed, 18 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index 9fbc071ef29b0c..11d25404d57166 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -933,6 +933,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
+                       int slot);
+ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);
+ int rvu_cpt_init(struct rvu *rvu);
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu);
+ #define NDC_AF_BANK_MASK       GENMASK_ULL(7, 0)
+ #define NDC_AF_BANK_LINE_MASK  GENMASK_ULL(31, 16)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 9b8a6046e6dff0..65ad7476e60983 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -609,6 +609,19 @@ static u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
+                         NPC_AF_MCAMEX_BANKX_ACTION(index, bank));
+ }
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu)
++{
++      /* For cn10k the upper two bits of the channel number are
++       * cpt channel number. with masking out these bits in the
++       * mcam entry, same entry used for NIX will allow packets
++       * received from cpt for parsing.
++       */
++      if (!is_rvu_otx2(rvu))
++              return NIX_CHAN_CPT_X2P_MASK;
++      else
++              return 0xFFFu;
++}
++
+ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+                                int nixlf, u64 chan, u8 *mac_addr)
+ {
+@@ -652,7 +665,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+       eth_broadcast_addr((u8 *)&req.mask.dmac);
+       req.features = BIT_ULL(NPC_DMAC);
+       req.channel = chan;
+-      req.chan_mask = 0xFFFU;
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.intf = pfvf->nix_rx_intf;
+       req.op = action.op;
+       req.hdr.pcifunc = 0; /* AF is requester */
+@@ -722,11 +735,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+        * mcam entry, same entry used for NIX will allow packets
+        * received from cpt for parsing.
+        */
+-      if (!is_rvu_otx2(rvu)) {
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      } else {
+-              req.chan_mask = 0xFFFU;
+-      }
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       if (chan_cnt > 1) {
+               if (!is_power_of_2(chan_cnt)) {
+@@ -915,16 +924,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+       ether_addr_copy(req.mask.dmac, mac_addr);
+       req.features = BIT_ULL(NPC_DMAC);
+-      /* For cn10k the upper two bits of the channel number are
+-       * cpt channel number. with masking out these bits in the
+-       * mcam entry, same entry used for NIX will allow packets
+-       * received from cpt for parsing.
+-       */
+-      if (!is_rvu_otx2(rvu))
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      else
+-              req.chan_mask = 0xFFFU;
+-
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.channel = chan;
+       req.intf = pfvf->nix_rx_intf;
+       req.entry = index;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+index 0f4e462d39c2ea..b0ec4757b10835 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+@@ -1354,7 +1354,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
+       /* ignore chan_mask in case pf func is not AF, revisit later */
+       if (!is_pffunc_af(req->hdr.pcifunc))
+-              req->chan_mask = 0xFFF;
++              req->chan_mask = rvu_get_cpt_chan_mask(rvu);
+       err = npc_check_unsupported_flows(rvu, req->features, req->intf);
+       if (err)
+-- 
+2.53.0
+
diff --git a/queue-6.6/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-6.6/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..1e04230
--- /dev/null
@@ -0,0 +1,58 @@
+From a316e6de01140387b8979a9115b96261c0b8cf59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 72db9f9e7beeae..81cb83caf62a15 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1403,8 +1403,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1412,9 +1414,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/ptp-vclock-switch-from-rcu-to-srcu.patch b/queue-6.6/ptp-vclock-switch-from-rcu-to-srcu.patch
new file mode 100644 (file)
index 0000000..693ea98
--- /dev/null
@@ -0,0 +1,85 @@
+From b67f6fcf4974611a75d6d508761f32139539f9b2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:11:47 +0200
+Subject: ptp: vclock: Switch from RCU to SRCU
+
+From: Kurt Kanzenbach <kurt@linutronix.de>
+
+[ Upstream commit 672bd0519e27c357c43b7f8c0d653fce3817d06e ]
+
+The usage of PTP vClocks leads immediately to the following issues with
+ptp4l with LOCKDEP and DEBUG_ATOMIC_SLEEP enabled: "BUG: sleeping function
+called from invalid context".
+
+ptp_convert_timestamp() acquires a mutex_t within a RCU read section.  This
+is illegal, because acquiring a mutex_t can result in voluntary scheduling
+request which is not allowed within a RCU read section.
+
+Replace the RCU usage with SRCU where sleeping is allowed.
+
+Reported-by: Florian Zeitz <florian.zeitz@schettke.com>
+Closes: https://lore.kernel.org/all/00a8cce8-410e-4038-98af-49be6d93d7bd@schettke.com/
+Fixes: 67d93ffc0f3c ("ptp: vclock: use mutex to fix "sleep on atomic" bug")
+Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260529-vclock_rcu-v2-1-02a5531fab92@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_vclock.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
+index 7d08ff3b30fc27..a88c4245937321 100644
+--- a/drivers/ptp/ptp_vclock.c
++++ b/drivers/ptp/ptp_vclock.c
+@@ -19,6 +19,8 @@ static DEFINE_SPINLOCK(vclock_hash_lock);
+ static DEFINE_READ_MOSTLY_HASHTABLE(vclock_hash, 8);
++DEFINE_STATIC_SRCU(vclock_srcu);
++
+ static void ptp_vclock_hash_add(struct ptp_vclock *vclock)
+ {
+       spin_lock(&vclock_hash_lock);
+@@ -37,7 +39,7 @@ static void ptp_vclock_hash_del(struct ptp_vclock *vclock)
+       spin_unlock(&vclock_hash_lock);
+-      synchronize_rcu();
++      synchronize_srcu(&vclock_srcu);
+ }
+ static int ptp_vclock_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+@@ -276,14 +278,16 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+ {
+       unsigned int hash = vclock_index % HASH_SIZE(vclock_hash);
+       struct ptp_vclock *vclock;
+-      u64 ns;
+       u64 vclock_ns = 0;
++      int srcu_idx;
++      u64 ns;
+       ns = ktime_to_ns(*hwtstamp);
+-      rcu_read_lock();
++      srcu_idx = srcu_read_lock(&vclock_srcu);
+-      hlist_for_each_entry_rcu(vclock, &vclock_hash[hash], vclock_hash_node) {
++      hlist_for_each_entry_srcu(vclock, &vclock_hash[hash], vclock_hash_node,
++                                srcu_read_lock_held(&vclock_srcu)) {
+               if (vclock->clock->index != vclock_index)
+                       continue;
+@@ -294,7 +298,7 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+               break;
+       }
+-      rcu_read_unlock();
++      srcu_read_unlock(&vclock_srcu, srcu_idx);
+       return ns_to_ktime(vclock_ns);
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-6.6/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..45ffd7a
--- /dev/null
@@ -0,0 +1,87 @@
+From dd12614d9fe07c5b69a599282360e960d8206b31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 5e9449b0c7907e..583d83dcb8426e 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2597,11 +2597,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
index 239da65d7954a45670d5828617f21514ff40442f..8814bbb948ad6e03fe8914cc84cb8c46e3a844bd 100644 (file)
@@ -207,3 +207,38 @@ bluetooth-hci_conn-fix-potential-uaf-in-set_cig_para.patch
 rdma-rxe-fix-trying-to-register-non-static-key-in-rx.patch
 hwmon-pmbus-core-protect-regulator-operations-with-m.patch
 disable-wattribute-alias-for-clang-23-and-newer.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-annotate-sk-sk_write_space-for-udp-sockmap.patch
+hsr-remove-warn_once-in-hsr_addr_is_self.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
+bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
+bluetooth-bnep-reject-short-frames-before-parsing.patch
+bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
+bluetooth-mgmt-fix-backward-compatibility-with-users.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ptp-vclock-switch-from-rcu-to-srcu.patch
+net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
+octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
+vxlan-vnifilter-send-notification-on-vni-add.patch
+vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
+ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
diff --git a/queue-6.6/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-6.6/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..951d174
--- /dev/null
@@ -0,0 +1,287 @@
+From 8d863acc11fd07ab88aeb2494b63588e7942d816 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index d0f397c9024201..2386bbd38ce78b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.6/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch b/queue-6.6/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
new file mode 100644 (file)
index 0000000..a82152c
--- /dev/null
@@ -0,0 +1,55 @@
+From 74189dbae90365313b57e12f51c47a3c1df59d02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:37 -0700
+Subject: vxlan: vnifilter: fix spurious notification on VNI update
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit 84683b5b60c7274e2c8f7f413d39d78d3db5540f ]
+
+When a VNI is re-added with the same attributes (e.g. same group or no
+group), vxlan_vni_update() sends a spurious RTM_NEWTUNNEL notification
+even though nothing changed.
+
+The bug is that 'if (changed)' tests whether the pointer is non-NULL,
+not the bool value it points to. Since every caller passes a valid
+pointer, the condition is always true and the notification fires
+unconditionally.
+
+Fix by dereferencing the pointer: 'if (*changed)'.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100
+ # bridge vni add vni 1000 dev vxlan100  # spurious notification
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-3-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index 1ab78a8bb9e011..272fa31ef07454 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -671,7 +671,7 @@ static int vxlan_vni_update(struct vxlan_dev *vxlan,
+       if (ret)
+               return ret;
+-      if (changed)
++      if (*changed)
+               vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-6.6/vxlan-vnifilter-send-notification-on-vni-add.patch b/queue-6.6/vxlan-vnifilter-send-notification-on-vni-add.patch
new file mode 100644 (file)
index 0000000..05b3541
--- /dev/null
@@ -0,0 +1,69 @@
+From baffd49b11485678cf5de56cedeff4fbe8cb1a23 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:36 -0700
+Subject: vxlan: vnifilter: send notification on VNI add
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit aa6ca1c5c338907817374b59f7551fd855a88754 ]
+
+When a new VNI is added to a vxlan device with vnifilter enabled,
+no RTM_NEWTUNNEL notification is sent to userspace. This means
+'bridge monitor vni' never shows VNI add events, even though
+VNI delete events are reported correctly.
+
+The bug is in vxlan_vni_add(), where the notification is guarded by
+'if (changed)'. The 'changed' flag is set by vxlan_vni_update_group()
+only when the multicast group or remote IP is modified, but for a
+new VNI added without a group (e.g. in L3 VxLAN interface scenarios),
+the function returns early without setting changed=true. Since this
+is a new VNI, the notification should be sent unconditionally.
+
+The notification is not guarded by the return value of
+vxlan_vni_update_group() because, at this point, the VNI has already
+been inserted into the hash table and list with no rollback on error.
+The VNI will be visible in 'bridge vni show' regardless, so userspace
+should be informed. This is consistent with vxlan_vni_del() which also
+notifies unconditionally.
+
+The 'if (changed)' guard remains correct in vxlan_vni_update(), which
+handles the case where a VNI already exists and is being re-added --
+there, we only want to notify if the group/remote actually changed.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100    # no notification
+ # bridge vni delete vni 1000 dev vxlan100 # notification received
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Reported-by: Chirag Shah <chirag@nvidia.com>
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-2-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index 06d19e90eadb59..1ab78a8bb9e011 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -769,8 +769,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+       err = vxlan_vni_update_group(vxlan, vninode, group, true, &changed,
+                                    extack);
+-      if (changed)
+-              vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
++      vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return err;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/6lowpan-fix-off-by-one-in-multicast-context-address-.patch b/queue-7.0/6lowpan-fix-off-by-one-in-multicast-context-address-.patch
new file mode 100644 (file)
index 0000000..90058ca
--- /dev/null
@@ -0,0 +1,67 @@
+From 3a2b003a87afe82302489a2704319c2e61dc8a44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:18:01 +0800
+Subject: 6lowpan: fix off-by-one in multicast context address compression
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 2a58899d11009bffc7b4b32a571858f381121837 ]
+
+The second memcpy in lowpan_iphc_mcast_ctx_addr_compress() uses
+&data[1] as destination and &ipaddr->s6_addr[11] as source, but
+both should be offset by one: &data[2] and &ipaddr->s6_addr[12]
+respectively.
+
+This off-by-one has two consequences:
+1. data[1] is overwritten with s6_addr[11], corrupting the RIID
+   field in the compressed multicast address
+2. data[5] is never written, so uninitialized kernel stack memory
+   is transmitted over the network via lowpan_push_hc_data(),
+   leaking kernel stack contents
+
+The correct inline data layout must match what the decompression
+function lowpan_uncompress_multicast_ctx_daddr() expects:
+  data[0..1] = s6_addr[1..2]  (flags/scope + RIID)
+  data[2..5] = s6_addr[12..15] (group ID)
+
+Also zero-initialize the data array as a defensive measure against
+similar bugs in the future.
+
+Fixes: 5609c185f24d ("6lowpan: iphc: add support for stateful compression")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Acked-by: Alexander Aring <aahringo@redhat.com>
+Link: https://patch.msgid.link/20260527081806.42747-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/6lowpan/iphc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
+index e116d308a8df6d..37eaff3f7b6940 100644
+--- a/net/6lowpan/iphc.c
++++ b/net/6lowpan/iphc.c
+@@ -1086,12 +1086,12 @@ static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
+                                             const struct lowpan_iphc_ctx *ctx,
+                                             const struct in6_addr *ipaddr)
+ {
+-      u8 data[6];
++      u8 data[6] = {};
+       /* flags/scope, reserved (RIID) */
+       memcpy(data, &ipaddr->s6_addr[1], 2);
+       /* group ID */
+-      memcpy(&data[1], &ipaddr->s6_addr[11], 4);
++      memcpy(&data[2], &ipaddr->s6_addr[12], 4);
+       lowpan_push_hc_data(hc_ptr, data, 6);
+       return LOWPAN_IPHC_DAM_00;
+-- 
+2.53.0
+
diff --git a/queue-7.0/af_unix-fix-inq_len-update-problem-in-partial-read.patch b/queue-7.0/af_unix-fix-inq_len-update-problem-in-partial-read.patch
new file mode 100644 (file)
index 0000000..bd2dcba
--- /dev/null
@@ -0,0 +1,60 @@
+From a86c442ef196fc179f43a72e5760089d3aa479b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 19:36:39 +0800
+Subject: af_unix: Fix inq_len update problem in partial read
+
+From: Jianyu Li <jianyu.li@mediatek.com>
+
+[ Upstream commit c1f07a7f2d47aeb9878301e7bb36bc1c2bc2be8e ]
+
+Currently inq_len is updated only when the whole skb is consumed.
+If only part of the data is read, following SIOCINQ query would
+get value greater than what actually left.
+
+This change update inq_len timely in unix_stream_read_generic(),
+and adjust unix_stream_read_skb() accordingly to prevent
+repetitive update.
+
+Fixes: f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().")
+Signed-off-by: Jianyu Li <jianyu.li@mediatek.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260601113640.231897-2-jianyu.li@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index c3d68bf26ce19b..62ec16c8ab2ede 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2882,7 +2882,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
+               return -EAGAIN;
+       }
+-      WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
++      WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb));
+ #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
+       if (skb == u->oob_skb) {
+@@ -3059,11 +3059,12 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
+                               unix_detach_fds(&scm, skb);
+                       }
+-                      if (unix_skb_len(skb))
+-                              break;
+-
+                       spin_lock(&sk->sk_receive_queue.lock);
+-                      WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
++                      WRITE_ONCE(u->inq_len, u->inq_len - chunk);
++                      if (unix_skb_len(skb)) {
++                              spin_unlock(&sk->sk_receive_queue.lock);
++                              break;
++                      }
+                       __skb_unlink(skb, &sk->sk_receive_queue);
+                       spin_unlock(&sk->sk_receive_queue.lock);
+-- 
+2.53.0
+
diff --git a/queue-7.0/arm-dts-gemini-fix-partition-offsets.patch b/queue-7.0/arm-dts-gemini-fix-partition-offsets.patch
new file mode 100644 (file)
index 0000000..518a21d
--- /dev/null
@@ -0,0 +1,54 @@
+From afc5f89fda6c6410c927f0721dfdce1f8e39f7d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 10:25:26 +0200
+Subject: ARM: dts: gemini: Fix partition offsets
+
+From: Linus Walleij <linusw@kernel.org>
+
+[ Upstream commit 66ac2df408ede627aaae588d4ce7e611dd25b4f9 ]
+
+These FIS partition offsets were never right: the comment clearly
+states the FIS index is at 0xfe0000 and 0x7f * 0x200000 is
+0xfe0000.
+
+Tested on the iTian SQ201.
+
+Fixes: d88b11ef91b1 ("ARM: dts: Fix up SQ201 flash access")
+Fixes: b5a923f8c739 ("ARM: dts: gemini: Switch to redboot partition parsing")
+Signed-off-by: Linus Walleij <linusw@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/gemini/gemini-sl93512r.dts | 2 +-
+ arch/arm/boot/dts/gemini/gemini-sq201.dts    | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/gemini/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini/gemini-sl93512r.dts
+index 4992ec276de92e..341dec9b636a8b 100644
+--- a/arch/arm/boot/dts/gemini/gemini-sl93512r.dts
++++ b/arch/arm/boot/dts/gemini/gemini-sl93512r.dts
+@@ -146,7 +146,7 @@ flash@30000000 {
+                       partitions {
+                               compatible = "redboot-fis";
+                               /* Eraseblock at 0xfe0000 */
+-                              fis-index-block = <0x1fc>;
++                              fis-index-block = <0x7f>;
+                       };
+               };
+diff --git a/arch/arm/boot/dts/gemini/gemini-sq201.dts b/arch/arm/boot/dts/gemini/gemini-sq201.dts
+index f8c6f6e5cdea6a..bfd1e8581ad67c 100644
+--- a/arch/arm/boot/dts/gemini/gemini-sq201.dts
++++ b/arch/arm/boot/dts/gemini/gemini-sq201.dts
+@@ -134,7 +134,7 @@ flash@30000000 {
+                       partitions {
+                               compatible = "redboot-fis";
+                               /* Eraseblock at 0xfe0000 */
+-                              fis-index-block = <0x1fc>;
++                              fis-index-block = <0x7f>;
+                       };
+               };
+-- 
+2.53.0
+
diff --git a/queue-7.0/arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch b/queue-7.0/arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch
new file mode 100644 (file)
index 0000000..4552f2a
--- /dev/null
@@ -0,0 +1,56 @@
+From 7f160e39baa43187760ad16bf5283a35df59b8ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Mar 2026 09:53:29 +0200
+Subject: ARM: dts: microchip: sam9x7: fix GMAC clock configuration
+
+From: Mihai Sain <mihai.sain@microchip.com>
+
+[ Upstream commit 765aaba18413a66f6c8fe8416336ca9b3dd98a79 ]
+
+The GMAC node incorrectly listed four clocks, including a separate tx_clk
+and a TSU GCK clock sourced from ID 67. According to the SAM9X7 clocking
+scheme, the GMAC uses only three clocks: HCLK, PCLK, and the TSU GCK
+derived from the GMAC peripheral clock (ID 24).
+
+Remove the unused tx_clk, update the clock-names accordingly, and correct
+the assigned clock to use GCK 24 instead of GCK 67. This aligns the device
+tree with the actual hardware clock topology and prevents misconfiguration
+of the GMAC clock tree.
+
+[root@SAM9X75 ~]$ cat /sys/kernel/debug/clk/clk_summary | grep gmac
+
+gmac_gclk      1       1        1        266666666   0          0     50000      Y         f802c000.ethernet           tsu_clk
+                                                                                           f802c000.ethernet           tsu_clk
+gmac_clk       2       2        0        266666666   0          0     50000      Y         f802c000.ethernet           hclk
+                                                                                           f802c000.ethernet           pclk
+
+Fixes: 41af45af8bc3 ("ARM: dts: at91: sam9x7: add device tree for SoC")
+Signed-off-by: Mihai Sain <mihai.sain@microchip.com>
+Link: https://lore.kernel.org/r/20260309075329.1528-5-mihai.sain@microchip.com
+[claudiu.beznea: massaged the patch description]
+Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/microchip/sam9x7.dtsi | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/boot/dts/microchip/sam9x7.dtsi b/arch/arm/boot/dts/microchip/sam9x7.dtsi
+index d242d7a934d0fa..c680a5033b6b4e 100644
+--- a/arch/arm/boot/dts/microchip/sam9x7.dtsi
++++ b/arch/arm/boot/dts/microchip/sam9x7.dtsi
+@@ -990,9 +990,9 @@ gmac: ethernet@f802c000 {
+                                    <62 IRQ_TYPE_LEVEL_HIGH 3>,        /* Queue 3 */
+                                    <63 IRQ_TYPE_LEVEL_HIGH 3>,        /* Queue 4 */
+                                    <64 IRQ_TYPE_LEVEL_HIGH 3>;        /* Queue 5 */
+-                      clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>, <&pmc PMC_TYPE_GCK 67>;
+-                      clock-names = "hclk", "pclk", "tx_clk", "tsu_clk";
+-                      assigned-clocks = <&pmc PMC_TYPE_GCK 67>;
++                      clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>;
++                      clock-names = "hclk", "pclk", "tsu_clk";
++                      assigned-clocks = <&pmc PMC_TYPE_GCK 24>;
+                       assigned-clock-rates = <266666666>;
+                       status = "disabled";
+               };
+-- 
+2.53.0
+
diff --git a/queue-7.0/arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch b/queue-7.0/arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch
new file mode 100644 (file)
index 0000000..014efa8
--- /dev/null
@@ -0,0 +1,53 @@
+From 7f0e8e0b7952a2ac957d31089cbe48677c6b42ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Mar 2026 21:53:37 -0300
+Subject: arm64: dts: qcom: x1-dell-thena: remove i2c20 (battery SMBus) and
+ reserve its pins
+
+From: Val Packett <val@packett.cool>
+
+[ Upstream commit 4b15b03166cc5d28e9912287b1f9b6607c8710ec ]
+
+i2c20 is used by the battmgr service on the ADSP to communicate with the
+SBS interface of the battery. Initializing it from Linux would break the
+battmgr functionality when booted in EL2. Mark those pins as reserved.
+
+Fixes: e7733b42111c ("arm64: dts: qcom: Add support for Dell Inspiron 7441 / Latitude 7455")
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
+Signed-off-by: Val Packett <val@packett.cool>
+Link: https://lore.kernel.org/r/20260312005731.12488-2-val@packett.cool
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+index 217ca8c7d81dae..488129bb1ae198 100644
+--- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+@@ -982,12 +982,6 @@ &i2c8 {
+       status = "okay";
+ };
+-&i2c20 {
+-      clock-frequency = <400000>;
+-
+-      status = "okay";
+-};
+-
+ &lpass_tlmm {
+       spkr_01_sd_n_active: spkr-01-sd-n-active-state {
+               pins = "gpio12";
+@@ -1308,6 +1302,7 @@ right_tweeter: speaker@0,1 {
+ &tlmm {
+       gpio-reserved-ranges = <44 4>,  /* SPI11 (TPM) */
+                              <76 4>,  /* SPI19 (TZ Protected) */
++                             <80 2>,  /* I2C20 (Battery SMBus) */
+                              <238 1>; /* UFS Reset */
+       cam_rgb_default: cam-rgb-default-state {
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch b/queue-7.0/bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
new file mode 100644 (file)
index 0000000..9c7c9e8
--- /dev/null
@@ -0,0 +1,72 @@
+From 6d6e869cb048ce84601bd21f0c8d40f0b14e9ea7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Apr 2026 17:39:53 +0800
+Subject: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame()
+ extension handling
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+[ Upstream commit 72b8deccff17a7644e0367e1aaf1a36cfb014324 ]
+
+In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
+BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:
+
+1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
+   performs a native-endian read. The BNEP protocol specifies this field
+   in big-endian (network byte order), and the same file correctly uses
+   get_unaligned_be16() for the identical fields in
+   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().
+
+2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
+   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
+   entry), the filter extension length field already represents the total
+   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
+   which reads the same field as a byte count and divides by 4 to get
+   the number of filter entries.
+
+   The bogus * 2 means skb_pull advances twice as far as it should,
+   either dropping valid data from the next header or causing the pull
+   to fail entirely when the doubled length exceeds the remaining skb.
+
+Fix by splitting the pull into two steps: first use skb_pull_data() to
+safely pull and validate the 3-byte fixed header (ctrl type + length),
+then pull the variable-length data using the properly decoded length.
+
+Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 6770d3a8acdf ("Bluetooth: bnep: reject short frames before parsing")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index b3cef7a4db5412..0de5df690bd0b2 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+                               goto badframe;
+                       break;
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET:
+-                      /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+-                      if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
++              case BNEP_FILTER_NET_TYPE_SET: {
++                      u8 *hdr;
++
++                      /* Pull ctrl type (1 b) + len (2 b) */
++                      hdr = skb_pull_data(skb, 3);
++                      if (!hdr)
++                              goto badframe;
++                      /* Pull data (len bytes); length is big-endian */
++                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+                               goto badframe;
+                       break;
++              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-bnep-reject-short-frames-before-parsing.patch b/queue-7.0/bluetooth-bnep-reject-short-frames-before-parsing.patch
new file mode 100644 (file)
index 0000000..15943a3
--- /dev/null
@@ -0,0 +1,170 @@
+From 69a2362aa638fabd25463cfe8d2bc07eb3fbd719 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 11:22:09 +0800
+Subject: Bluetooth: bnep: reject short frames before parsing
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 6770d3a8acdf9151769180cc3710346c4cfbe6f0 ]
+
+A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
+packet type byte immediately and, for control packets, reads the control
+opcode and setup UUID-size byte before proving that those bytes are
+present. bnep_rx_control() also dereferences the control opcode without
+rejecting an empty control payload.
+
+Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
+return gates each dereference. Split the control handler so the frame
+path can pass an opcode that has already been pulled, and keep the
+byte-buffer wrapper for extension control payloads.
+
+For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
+setup payload. struct bnep_setup_conn_req carries destination and source
+service UUIDs after that byte, each uuid_size bytes, so the parser now
+documents that tuple explicitly instead of leaving the pull length as an
+opaque multiplication.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
+The buggy address belongs to the object at ffff88800c0f7908 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 1-byte
+region [ffff88800c0f7908, ffff88800c0f7909)
+Read of size 1
+Call trace:
+  dump_stack_lvl+0xb3/0x140 (?:?)
+  print_address_description+0x57/0x3a0 (?:?)
+  bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
+  print_report+0xb9/0x2b0 (?:?)
+  __virt_addr_valid+0x1ba/0x3a0 (?:?)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  kasan_addr_to_slab+0x21/0x60 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
+  worker_thread+0x65c/0xe40 (?:?)
+  __kthread_parkme+0x184/0x230 (?:?)
+  kthread+0x35e/0x470 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  ret_from_fork+0x586/0x870 (?:?)
+  __switch_to+0x74f/0xdc0 (?:?)
+  ret_from_fork_asm+0x1a/0x30 (?:?)
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
+index 0de5df690bd0b2..5c5f53ff30e8e5 100644
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
+       return 0;
+ }
+-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
++                             int len)
+ {
+-      u8  cmd = *(u8 *)data;
+       int err = 0;
+-      data++;
+-      len--;
+-
+       switch (cmd) {
+       case BNEP_CMD_NOT_UNDERSTOOD:
+       case BNEP_SETUP_CONN_RSP:
+@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+       return err;
+ }
++static int bnep_rx_control(struct bnep_session *s, void *data, int len)
++{
++      if (len < 1)
++              return -EILSEQ;
++
++      return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
++}
++
+ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct bnep_ext_hdr *h;
+@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+ {
+       struct net_device *dev = s->dev;
+       struct sk_buff *nskb;
++      u8 *data;
+       u8 type, ctrl_type;
+       dev->stats.rx_bytes += skb->len;
+-      type = *(u8 *) skb->data;
+-      skb_pull(skb, 1);
+-      ctrl_type = *(u8 *)skb->data;
++      data = skb_pull_data(skb, sizeof(type));
++      if (!data)
++              goto badframe;
++      type = *data;
+       if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
+               goto badframe;
+       if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
+-              if (bnep_rx_control(s, skb->data, skb->len) < 0) {
++              data = skb_pull_data(skb, sizeof(ctrl_type));
++              if (!data)
++                      goto badframe;
++              ctrl_type = *data;
++
++              if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
+                       dev->stats.tx_errors++;
+                       kfree_skb(skb);
+                       return 0;
+@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+               /* Verify and pull ctrl message since it's already processed */
+               switch (ctrl_type) {
+-              case BNEP_SETUP_CONN_REQ:
+-                      /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+-                      if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
++              case BNEP_SETUP_CONN_REQ: {
++                      u8 uuid_size;
++
++                      /* Pull uuid_size and the dst/src service UUIDs. */
++                      data = skb_pull_data(skb, sizeof(uuid_size));
++                      if (!data)
++                              goto badframe;
++                      uuid_size = *data;
++                      if (!skb_pull(skb, uuid_size + uuid_size))
+                               goto badframe;
+                       break;
++              }
+               case BNEP_FILTER_MULTI_ADDR_SET:
+-              case BNEP_FILTER_NET_TYPE_SET: {
+-                      u8 *hdr;
+-
+-                      /* Pull ctrl type (1 b) + len (2 b) */
+-                      hdr = skb_pull_data(skb, 3);
+-                      if (!hdr)
++              case BNEP_FILTER_NET_TYPE_SET:
++                      /* Pull: len (2 b), data (len bytes) */
++                      data = skb_pull_data(skb, sizeof(u16));
++                      if (!data)
+                               goto badframe;
+-                      /* Pull data (len bytes); length is big-endian */
+-                      if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
++                      if (!skb_pull(skb, get_unaligned_be16(data)))
+                               goto badframe;
+                       break;
+-              }
+               default:
+                       kfree_skb(skb);
+                       return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch b/queue-7.0/bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
new file mode 100644 (file)
index 0000000..78ba780
--- /dev/null
@@ -0,0 +1,58 @@
+From 97c2378cab696f413155914b3ddfc82def7b9ae5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 08:54:26 +0530
+Subject: Bluetooth: fix memory leak in error path of hci_alloc_dev()
+
+From: Bharath Reddy <kbreddy.rpbc@gmail.com>
+
+[ Upstream commit 37b3009bf5976e8ab77c8b9a9bc3bbd7ff49e37f ]
+
+Early failures in Bluetooth HCI UART configuration leak SRCU percpu
+memory.
+
+When device initialization fails before hci_register_dev() completes,
+the HCI_UNREGISTER flag is never set. As a result, when the device
+reference count reaches zero, bt_host_release() evaluates this flag as
+false and falls back to a direct kfree(hdev).
+
+Because hci_release_dev() is bypassed, the SRCU struct initialized
+early in hci_alloc_dev() is never cleaned up, resulting in a leak of
+percpu memory.
+
+Fix the leak by explicitly calling cleanup_srcu_struct() in the
+fallback (unregistered) branch of bt_host_release() before freeing
+the device.
+
+Reported-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=535ecc844591e50588a5
+Tested-by: syzbot+535ecc844591e50588a5@syzkaller.appspotmail.com
+Fixes: 1d6123102e9f ("Bluetooth: hci_core: Fix use-after-free in vhci_flush()")
+Signed-off-by: Bharath Reddy <kbreddy.rpbc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sysfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
+index 041ce9adc378ae..8957ce7c21b76c 100644
+--- a/net/bluetooth/hci_sysfs.c
++++ b/net/bluetooth/hci_sysfs.c
+@@ -83,10 +83,12 @@ static void bt_host_release(struct device *dev)
+ {
+       struct hci_dev *hdev = to_hci_dev(dev);
+-      if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
++      if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_release_dev(hdev);
+-      else
++      } else {
++              cleanup_srcu_struct(&hdev->srcu);
+               kfree(hdev);
++      }
+       module_put(THIS_MODULE);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-iso-fix-a-use-after-free-of-the-hci_conn-p.patch b/queue-7.0/bluetooth-iso-fix-a-use-after-free-of-the-hci_conn-p.patch
new file mode 100644 (file)
index 0000000..50d9cd2
--- /dev/null
@@ -0,0 +1,48 @@
+From a7e58d3d636a0a157ef84216335f4832960d0d10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 14:52:09 -0400
+Subject: Bluetooth: ISO: Fix a use-after-free of the hci_conn pointer
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit f50331f2a1441ec49988832c3a95f2edacc47322 ]
+
+In iso_sock_rebind_bc(), the bis pointer is cached, then the socket lock is
+dropped:
+       bis = iso_pi(sk)->conn->hcon;
+       /* Release the socket before lookups since that requires hci_dev_lock
+        * which shall not be acquired while holding sock_lock for proper
+        * ordering.
+        */
+       release_sock(sk);
+       hci_dev_lock(bis->hdev);
+
+During the unlocked window, could a concurrent close() destroy the connection
+and free the bis structure, causing hci_dev_lock(bis->hdev) to access memory
+after it is freed, fix this by using the hdev reference which was safely
+acquired via iso_conn_get_hdev().
+
+Fixes: d3413703d5f8 ("Bluetooth: ISO: Add support to bind to trigger PAST")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 2363b6135c6f1b..05a3f1e554fe67 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1090,7 +1090,7 @@ static int iso_sock_rebind_bc(struct sock *sk, struct sockaddr_iso *sa,
+        * ordering.
+        */
+       release_sock(sk);
+-      hci_dev_lock(bis->hdev);
++      hci_dev_lock(hdev);
+       lock_sock(sk);
+       if (!iso_pi(sk)->conn || iso_pi(sk)->conn->hcon != bis) {
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch b/queue-7.0/bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch
new file mode 100644 (file)
index 0000000..26d6d7d
--- /dev/null
@@ -0,0 +1,157 @@
+From c57b2f2f5ec21a8f73d63b92cdca6f9069a6cfae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 20:19:07 +0900
+Subject: Bluetooth: ISO: Fix data-race on iso_pi fields in hci_get_route calls
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 9ca7053d6215d89c33f28893bfd1625a32919d3f ]
+
+iso_connect_bis(), iso_connect_cis(), iso_listen_bis(), and
+iso_conn_big_sync() call hci_get_route() using iso_pi(sk)->dst,
+iso_pi(sk)->src, and iso_pi(sk)->src_type without holding lock_sock().
+
+These fields may be modified concurrently by connect() or setsockopt()
+on the same socket, resulting in data-races reported by KCSAN.
+
+Fix this by snapshotting the required fields under lock_sock() before
+calling hci_get_route().
+
+BUG: KCSAN: data-race in memcmp+0x45/0xb0
+
+race at unknown origin, with read to 0xffff8880122135cf of 1 bytes
+by task 333 on cpu 1:
+ memcmp+0x45/0xb0
+ hci_get_route+0x27e/0x490
+ iso_connect_cis+0x4c/0xa10
+ iso_sock_connect+0x60e/0xb30
+ __sys_connect_file+0xbd/0xe0
+ __sys_connect+0xe0/0x110
+ __x64_sys_connect+0x40/0x50
+ x64_sys_call+0xcad/0x1c60
+ do_syscall_64+0x133/0x590
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 241f51931c35 ("Bluetooth: ISO: Avoid circular locking dependency")
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 60 +++++++++++++++++++++++++++++++++------------
+ 1 file changed, 44 insertions(+), 16 deletions(-)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 05a3f1e554fe67..34e4803313d130 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -337,12 +337,20 @@ static int iso_connect_bis(struct sock *sk)
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      u8 src_type, bc_sid;
+       int err;
+-      BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      bc_sid = iso_pi(sk)->bc_sid;
++      release_sock(sk);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      BT_DBG("%pMR (SID 0x%2.2x)", &src, bc_sid);
++
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -434,12 +442,19 @@ static int iso_connect_cis(struct sock *sk)
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      u8 src_type;
+       int err;
+-      BT_DBG("%pMR -> %pMR", &iso_pi(sk)->src, &iso_pi(sk)->dst);
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      release_sock(sk);
++
++      BT_DBG("%pMR -> %pMR", &src, &dst);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -1220,18 +1235,25 @@ static int iso_sock_connect(struct socket *sock, struct sockaddr_unsized *addr,
+ static int iso_listen_bis(struct sock *sk)
+ {
+-      struct hci_dev *hdev;
+-      int err = 0;
+       struct iso_conn *conn;
+       struct hci_conn *hcon;
++      struct hci_dev *hdev;
++      bdaddr_t src, dst;
++      u8 src_type, bc_sid;
++      int err = 0;
++
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      bc_sid = iso_pi(sk)->bc_sid;
++      release_sock(sk);
+-      BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
+-             &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
++      BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &src, &dst, bc_sid);
+       write_lock(&iso_sk_list.lock);
+-      if (__iso_get_sock_listen_by_sid(&iso_pi(sk)->src, &iso_pi(sk)->dst,
+-                                       iso_pi(sk)->bc_sid))
++      if (__iso_get_sock_listen_by_sid(&src, &dst, bc_sid))
+               err = -EADDRINUSE;
+       write_unlock(&iso_sk_list.lock);
+@@ -1239,8 +1261,7 @@ static int iso_listen_bis(struct sock *sk)
+       if (err)
+               return err;
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -1576,9 +1597,16 @@ static void iso_conn_big_sync(struct sock *sk)
+ {
+       int err;
+       struct hci_dev *hdev;
++      bdaddr_t src, dst;
++      u8 src_type;
++
++      lock_sock(sk);
++      bacpy(&src, &iso_pi(sk)->src);
++      bacpy(&dst, &iso_pi(sk)->dst);
++      src_type = iso_pi(sk)->src_type;
++      release_sock(sk);
+-      hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+-                           iso_pi(sk)->src_type);
++      hdev = hci_get_route(&dst, &src, src_type);
+       if (!hdev)
+               return;
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch b/queue-7.0/bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch
new file mode 100644 (file)
index 0000000..26fa1cd
--- /dev/null
@@ -0,0 +1,36 @@
+From 0ff382f753907d73688003fbe6dbc5edc86a9a95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 14:45:42 -0400
+Subject: Bluetooth: ISO: Fix not releasing hdev reference on iso_conn_big_sync
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 5cbf290b79351971f20c7a533247e8d58a3f970c ]
+
+hci_get_route() returns a reference-counted hci_dev pointer via
+hci_dev_hold(). The function exits normally or with an error without ever
+releasing it.
+
+Fixes: 07a9342b94a9 ("Bluetooth: ISO: Send BIG Create Sync via hci_sync")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index a6bd608cbda69d..2363b6135c6f1b 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1603,6 +1603,7 @@ static void iso_conn_big_sync(struct sock *sk)
+       release_sock(sk);
+       hci_dev_unlock(hdev);
++      hci_dev_put(hdev);
+ }
+ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-mgmt-fix-backward-compatibility-with-users.patch b/queue-7.0/bluetooth-mgmt-fix-backward-compatibility-with-users.patch
new file mode 100644 (file)
index 0000000..d17cea1
--- /dev/null
@@ -0,0 +1,43 @@
+From cf931e2c7a943feeb0868202fe89f320fd391d9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:48:34 -0400
+Subject: Bluetooth: MGMT: Fix backward compatibility with userspace
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 149324fc762c2a7acef9c26790566f81f475e51f ]
+
+bluetoothd has a bug with makes it send extra bytes as part of
+MGMT_OP_ADD_EXT_ADV_DATA which are now being checked to be the
+exact the expected length, relax this so only when the expected
+length is greater than the data length to cause an error since
+that would result in accessing invalid memory, otherwise just
+ignore the extra bytes.
+
+Link: https://lore.kernel.org/linux-bluetooth/20260602204749.210857-1-luiz.dentz@gmail.com/T/#u
+Fixes: d3f7d17960ed ("Bluetooth: MGMT: validate Add Extended Advertising Data length")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 027b266ccc747c..f4aa814a039759 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -9114,8 +9114,9 @@ static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data,
+       BT_DBG("%s", hdev->name);
+-      expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len);
+-      if (expected_len != data_len)
++      expected_len = struct_size(cp, data, cp->adv_data_len +
++                                 cp->scan_rsp_len);
++      if (expected_len > data_len)
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
+                                      MGMT_STATUS_INVALID_PARAMS);
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch b/queue-7.0/bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
new file mode 100644 (file)
index 0000000..84afcfc
--- /dev/null
@@ -0,0 +1,73 @@
+From 7b42deebfbef9a0efb3b72a0e7393f00ff1241e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 17:45:06 +0800
+Subject: Bluetooth: MGMT: validate advertising TLV before type checks
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit de23fb62259aa01d294f77238ae3b835eb674413 ]
+
+tlv_data_is_valid() reads each advertising data field length from
+data[i], then inspects data[i + 1] for managed EIR types before
+checking that the current field still fits inside the supplied buffer.
+
+A malformed field whose length byte is the last byte of the buffer can
+therefore make the parser read one byte past the advertising data.
+
+KASAN reported the following when a malformed MGMT_OP_ADD_ADVERTISING
+request reached that path:
+
+  BUG: KASAN: vmalloc-out-of-bounds in tlv_data_is_valid()
+  Read of size 1
+  Call trace:
+    tlv_data_is_valid()
+    add_advertising()
+    hci_mgmt_cmd()
+    hci_sock_sendmsg()
+
+Move the existing element-length check before any type-octet inspection
+so each non-empty element is proven to contain its type byte before the
+parser looks at data[i + 1].
+
+Fixes: 2bb36870e8cb ("Bluetooth: Unify advertising instance flags check")
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index de5bd6b637b205..027b266ccc747c 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -8638,6 +8638,12 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (!cur_len)
+                       continue;
++              /* If the current field length would exceed the total data
++               * length, then it's invalid.
++               */
++              if (i + cur_len >= len)
++                      return false;
++
+               if (data[i + 1] == EIR_FLAGS &&
+                   (!is_adv_data || flags_managed(adv_flags)))
+                       return false;
+@@ -8654,12 +8660,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+               if (data[i + 1] == EIR_APPEARANCE &&
+                   appearance_managed(adv_flags))
+                       return false;
+-
+-              /* If the current field length would exceed the total data
+-               * length, then it's invalid.
+-               */
+-              if (i + cur_len >= len)
+-                      return false;
+       }
+       return true;
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch b/queue-7.0/bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
new file mode 100644 (file)
index 0000000..442e6ba
--- /dev/null
@@ -0,0 +1,126 @@
+From d0766b2711ddc80630c3f27eaf06fab67655d30d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 15:56:41 +0800
+Subject: Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+[ Upstream commit 43c441edacf953b39517a44f5e5e10a93618b226 ]
+
+rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
+but returns the selected listener after dropping that lock without
+taking a reference. rfcomm_connect_ind() then locks the listener,
+queues a child socket on it, and may notify it after unlocking it.
+
+The buggy scenario involves two paths, with each column showing the
+order within that path:
+
+rfcomm_connect_ind():            listener close:
+  1. Find parent in              1. close() enters
+     rfcomm_get_sock_by_channel()   rfcomm_sock_release().
+  2. Drop rfcomm_sk_list.lock    2. rfcomm_sock_shutdown()
+     without pinning parent.        closes the listener.
+  3. Call lock_sock(parent) and  3. rfcomm_sock_kill()
+     bt_accept_enqueue(parent,      unlinks and puts parent.
+     sk, true).
+  4. Read parent flags and may   4. parent can be freed.
+     call sk_state_change().
+
+If close wins the race, parent can be freed before
+rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
+deferred-setup callback.
+
+Take a reference on the listener before leaving rfcomm_sk_list.lock.
+After lock_sock() succeeds, recheck that it is still in BT_LISTEN
+before queueing a child, cache the deferred-setup bit while the parent
+is locked, and drop the reference after the last parent use.
+
+KASAN reported a slab-use-after-free in lock_sock_nested() from
+rfcomm_connect_ind(), with the freeing stack going through
+rfcomm_sock_kill() and rfcomm_sock_release().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index bd7d959c6e9eb8..805ed5d28ed668 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -122,7 +122,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
+ }
+ /* Find socket with channel and source bdaddr.
+- * Returns closest match.
++ * Returns closest match with an extra reference held.
+  */
+ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
+ {
+@@ -136,15 +136,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
+               if (rfcomm_pi(sk)->channel == channel) {
+                       /* Exact match. */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, src))
++                      if (!bacmp(&rfcomm_pi(sk)->src, src)) {
++                              sock_hold(sk);
+                               break;
++                      }
+                       /* Closest match */
+-                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
++                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
++                              if (sk1)
++                                      sock_put(sk1);
++
+                               sk1 = sk;
++                              sock_hold(sk1);
++                      }
+               }
+       }
++      if (sk && sk1)
++              sock_put(sk1);
++
+       read_unlock(&rfcomm_sk_list.lock);
+       return sk ? sk : sk1;
+@@ -941,6 +951,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ {
+       struct sock *sk, *parent;
+       bdaddr_t src, dst;
++      bool defer_setup = false;
+       int result = 0;
+       BT_DBG("session %p channel %d", s, channel);
+@@ -954,6 +965,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+       lock_sock(parent);
++      if (parent->sk_state != BT_LISTEN)
++              goto done;
++
++      defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
++
+       /* Check for backlog size */
+       if (sk_acceptq_is_full(parent)) {
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
+@@ -981,9 +997,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ done:
+       release_sock(parent);
+-      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
++      if (defer_setup)
+               parent->sk_state_change(parent);
++      sock_put(parent);
++
+       return result;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch b/queue-7.0/bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
new file mode 100644 (file)
index 0000000..d5c7e23
--- /dev/null
@@ -0,0 +1,167 @@
+From c7f496bb94ed3d52beae4bc4143ffee4cc879bc8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:04:43 +0900
+Subject: Bluetooth: RFCOMM: validate skb length in MCC handlers
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 23882b828c3c8c51d0c946446a396b10abb3b16b ]
+
+The RFCOMM MCC handlers cast skb->data to protocol-specific structs
+without validating skb->len first. A malicious remote device can send
+truncated MCC frames and trigger out-of-bounds reads in these handlers.
+
+Fix this by using skb_pull_data() to validate and access the required
+data before dereferencing it.
+
+rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
+1-byte RPN requests. Handle this by validating only the DLCI byte first,
+and validating the full struct only when len > 1.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
+ 1 file changed, 49 insertions(+), 18 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
+index 611a9a94151ecf..33d4d6fdf8681f 100644
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -1431,10 +1431,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
+ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_pn *pn = (void *) skb->data;
++      struct rfcomm_pn *pn;
+       struct rfcomm_dlc *d;
+-      u8 dlci = pn->dlci;
++      u8 dlci;
++
++      pn = skb_pull_data(skb, sizeof(*pn));
++      if (!pn)
++              return -EILSEQ;
++      dlci = pn->dlci;
+       BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
+       if (!dlci)
+@@ -1483,8 +1488,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
+ {
+-      struct rfcomm_rpn *rpn = (void *) skb->data;
+-      u8 dlci = __get_dlci(rpn->dlci);
++      struct rfcomm_rpn *rpn;
++      u8 dlci;
+       u8 bit_rate  = 0;
+       u8 data_bits = 0;
+@@ -1495,15 +1500,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+       u8 xoff_char = 0;
+       u16 rpn_mask = RFCOMM_RPN_PM_ALL;
+-      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+-              dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+-              rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++      if (len == 1) {
++              rpn = skb_pull_data(skb, 1);
++              if (!rpn)
++                      return -EILSEQ;
+-      if (!cr)
+-              return 0;
++              dlci = __get_dlci(rpn->dlci);
++
++              if (!cr)
++                      return 0;
+-      if (len == 1) {
+-              /* This is a request, return default (according to ETSI TS 07.10) settings */
+               bit_rate  = RFCOMM_RPN_BR_9600;
+               data_bits = RFCOMM_RPN_DATA_8;
+               stop_bits = RFCOMM_RPN_STOP_1;
+@@ -1514,6 +1520,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+               goto rpn_out;
+       }
++      rpn = skb_pull_data(skb, sizeof(*rpn));
++      if (!rpn)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rpn->dlci);
++
++      BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
++             dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
++             rpn->xon_char, rpn->xoff_char, rpn->param_mask);
++
++      if (!cr)
++              return 0;
++
+       /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+        * no parity, no flow control lines, normal XON/XOFF chars */
+@@ -1589,9 +1608,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
+ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_rls *rls = (void *) skb->data;
+-      u8 dlci = __get_dlci(rls->dlci);
++      struct rfcomm_rls *rls;
++      u8 dlci;
++      rls = skb_pull_data(skb, sizeof(*rls));
++      if (!rls)
++              return -EILSEQ;
++
++      dlci = __get_dlci(rls->dlci);
+       BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+       if (!cr)
+@@ -1608,10 +1632,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+ {
+-      struct rfcomm_msc *msc = (void *) skb->data;
++      struct rfcomm_msc *msc;
+       struct rfcomm_dlc *d;
+-      u8 dlci = __get_dlci(msc->dlci);
++      u8 dlci;
++
++      msc = skb_pull_data(skb, sizeof(*msc));
++      if (!msc)
++              return -EILSEQ;
++      dlci = __get_dlci(msc->dlci);
+       BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
+       d = rfcomm_dlc_get(s, dlci);
+@@ -1644,17 +1673,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
+ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
+ {
+-      struct rfcomm_mcc *mcc = (void *) skb->data;
++      struct rfcomm_mcc *mcc;
+       u8 type, cr, len;
++      mcc = skb_pull_data(skb, sizeof(*mcc));
++      if (!mcc)
++              return -EILSEQ;
++
+       cr   = __test_cr(mcc->type);
+       type = __get_mcc_type(mcc->type);
+       len  = __get_mcc_len(mcc->len);
+       BT_DBG("%p type 0x%x cr %d", s, type, cr);
+-      skb_pull(skb, 2);
+-
+       switch (type) {
+       case RFCOMM_PN:
+               rfcomm_recv_pn(s, cr, skb);
+-- 
+2.53.0
+
diff --git a/queue-7.0/bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch b/queue-7.0/bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch
new file mode 100644 (file)
index 0000000..9c832a3
--- /dev/null
@@ -0,0 +1,96 @@
+From c986675b2cfe2eb5eecbae3df87716a828494a7c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 20:19:08 +0900
+Subject: Bluetooth: SCO: Fix data-race on sco_pi fields in sco_connect
+
+From: SeungJu Cheon <suunj1331@gmail.com>
+
+[ Upstream commit 4847c5bca22227100ae69e96af86618b6fd2671f ]
+
+sco_sock_connect() copies the destination address into sco_pi(sk)->dst
+under lock_sock(), then releases the lock and calls sco_connect(),
+which reads dst, src, setting, and codec without holding lock_sock() in
+hci_get_route() and hci_connect_sco().
+
+These fields may be modified concurrently by connect(), bind(), or
+setsockopt() on the same socket, resulting in data-races reported by
+KCSAN.
+
+Fix this by snapshotting dst, src, setting, and codec under lock_sock()
+at the start of sco_connect() before passing them to hci_get_route()
+and hci_connect_sco().
+
+BUG: KCSAN: data-race in memcmp+0x45/0xb0
+
+race at unknown origin, with read to 0xffff88800e6b0dd0 of 1 bytes
+by task 315 on cpu 0:
+ memcmp+0x45/0xb0
+ hci_connect_acl+0x1b7/0x6b0
+ hci_connect_sco+0x4d/0xb30
+ sco_sock_connect+0x27b/0xd60
+ __sys_connect_file+0xbd/0xe0
+ __sys_connect+0xe0/0x110
+ __x64_sys_connect+0x40/0x50
+ x64_sys_call+0xcad/0x1c60
+ do_syscall_64+0x133/0x590
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 9a8ec9e8ebb5 ("Bluetooth: SCO: Fix possible circular locking dependency on sco_connect_cfm")
+Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/sco.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 770b9d6fad88f9..47ff4b8d1ae2cd 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -312,11 +312,21 @@ static int sco_connect(struct sock *sk)
+       struct sco_conn *conn;
+       struct hci_conn *hcon;
+       struct hci_dev  *hdev;
++      bdaddr_t src, dst;
++      struct bt_codec codec;
++      __u16 setting;
+       int err, type;
+-      BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
++      lock_sock(sk);
++      bacpy(&src, &sco_pi(sk)->src);
++      bacpy(&dst, &sco_pi(sk)->dst);
++      setting = sco_pi(sk)->setting;
++      codec = sco_pi(sk)->codec;
++      release_sock(sk);
++
++      BT_DBG("%pMR -> %pMR", &src, &dst);
+-      hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
++      hdev = hci_get_route(&dst, &src, BDADDR_BREDR);
+       if (!hdev)
+               return -EHOSTUNREACH;
+@@ -327,7 +337,7 @@ static int sco_connect(struct sock *sk)
+       else
+               type = SCO_LINK;
+-      switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
++      switch (setting & SCO_AIRMODE_MASK) {
+       case SCO_AIRMODE_TRANSP:
+               if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
+                       err = -EOPNOTSUPP;
+@@ -336,8 +346,8 @@ static int sco_connect(struct sock *sk)
+               break;
+       }
+-      hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
+-                             sco_pi(sk)->setting, &sco_pi(sk)->codec,
++      hcon = hci_connect_sco(hdev, type, &dst,
++                             setting, &codec,
+                              READ_ONCE(sk->sk_sndtimeo));
+       if (IS_ERR(hcon)) {
+               err = PTR_ERR(hcon);
+-- 
+2.53.0
+
diff --git a/queue-7.0/bonding-annotate-data-races-arcound-churn-variables.patch b/queue-7.0/bonding-annotate-data-races-arcound-churn-variables.patch
new file mode 100644 (file)
index 0000000..13d9cf6
--- /dev/null
@@ -0,0 +1,120 @@
+From 4a9199a8e7987814d4f2738834e1c8efa60a8f11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 12:35:14 +0000
+Subject: bonding: annotate data-races arcound churn variables
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b47ff80f280e18ad2310f44293cc057d9b64ff11 ]
+
+These fields are updated asynchronously by the bonding state machine
+in ad_churn_machine() while holding bond->mode_lock.
+
+bond_info_show_slave() and bond_fill_slave_info() read them without
+bond->mode_lock being held, we need to add READ_ONCE() and
+WRITE_ONCE() annotations.
+
+Note that AD_CHURN_MONITOR, AD_CHURN, and AD_NO_CHURN are defined
+exclusively in (kernel private) include/net/bond_3ad.h header.
+
+They should be moved to include/uapi/linux/if_bonding.h or userspace
+tools will have to hardcode their values.
+
+Fixes: 4916f2e2f3fc ("bonding: print churn state via netlink")
+Fixes: 14c9551a32eb ("bonding: Implement port churn-machine (AD standard 43.4.17).")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260603123514.388226-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_3ad.c     | 18 ++++++++++--------
+ drivers/net/bonding/bond_netlink.c |  4 ++--
+ drivers/net/bonding/bond_procfs.c  |  8 ++++----
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
+index f0aa7d2f21717a..985ef66dc3331e 100644
+--- a/drivers/net/bonding/bond_3ad.c
++++ b/drivers/net/bonding/bond_3ad.c
+@@ -1386,8 +1386,8 @@ static void ad_churn_machine(struct port *port)
+ {
+       if (port->sm_vars & AD_PORT_CHURNED) {
+               port->sm_vars &= ~AD_PORT_CHURNED;
+-              port->sm_churn_actor_state = AD_CHURN_MONITOR;
+-              port->sm_churn_partner_state = AD_CHURN_MONITOR;
++              WRITE_ONCE(port->sm_churn_actor_state, AD_CHURN_MONITOR);
++              WRITE_ONCE(port->sm_churn_partner_state, AD_CHURN_MONITOR);
+               port->sm_churn_actor_timer_counter =
+                       __ad_timer_to_ticks(AD_ACTOR_CHURN_TIMER, 0);
+               port->sm_churn_partner_timer_counter =
+@@ -1398,20 +1398,22 @@ static void ad_churn_machine(struct port *port)
+           !(--port->sm_churn_actor_timer_counter) &&
+           port->sm_churn_actor_state == AD_CHURN_MONITOR) {
+               if (port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION) {
+-                      port->sm_churn_actor_state = AD_NO_CHURN;
++                      WRITE_ONCE(port->sm_churn_actor_state, AD_NO_CHURN);
+               } else {
+-                      port->churn_actor_count++;
+-                      port->sm_churn_actor_state = AD_CHURN;
++                      WRITE_ONCE(port->churn_actor_count,
++                                 port->churn_actor_count + 1);
++                      WRITE_ONCE(port->sm_churn_actor_state, AD_CHURN);
+               }
+       }
+       if (port->sm_churn_partner_timer_counter &&
+           !(--port->sm_churn_partner_timer_counter) &&
+           port->sm_churn_partner_state == AD_CHURN_MONITOR) {
+               if (port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) {
+-                      port->sm_churn_partner_state = AD_NO_CHURN;
++                      WRITE_ONCE(port->sm_churn_partner_state, AD_NO_CHURN);
+               } else {
+-                      port->churn_partner_count++;
+-                      port->sm_churn_partner_state = AD_CHURN;
++                      WRITE_ONCE(port->churn_partner_count,
++                                 port->churn_partner_count + 1);
++                      WRITE_ONCE(port->sm_churn_partner_state, AD_CHURN);
+               }
+       }
+ }
+diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
+index c7d3e0602c831d..90365d3f7ebff7 100644
+--- a/drivers/net/bonding/bond_netlink.c
++++ b/drivers/net/bonding/bond_netlink.c
+@@ -82,10 +82,10 @@ static int bond_fill_slave_info(struct sk_buff *skb,
+                               goto nla_put_failure_rcu;
+                       if (nla_put_u8(skb, IFLA_BOND_SLAVE_AD_CHURN_ACTOR_STATE,
+-                                     ad_port->sm_churn_actor_state))
++                                     READ_ONCE(ad_port->sm_churn_actor_state)))
+                               goto nla_put_failure_rcu;
+                       if (nla_put_u8(skb, IFLA_BOND_SLAVE_AD_CHURN_PARTNER_STATE,
+-                                     ad_port->sm_churn_partner_state))
++                                     READ_ONCE(ad_port->sm_churn_partner_state)))
+                               goto nla_put_failure_rcu;
+               }
+               rcu_read_unlock();
+diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
+index 0c0146b7617721..62a5b40b43a28e 100644
+--- a/drivers/net/bonding/bond_procfs.c
++++ b/drivers/net/bonding/bond_procfs.c
+@@ -220,13 +220,13 @@ static void bond_info_show_slave(struct seq_file *seq,
+                       seq_printf(seq, "Aggregator ID: %d\n",
+                                  agg->aggregator_identifier);
+                       seq_printf(seq, "Actor Churn State: %s\n",
+-                                 bond_3ad_churn_desc(port->sm_churn_actor_state));
++                                 bond_3ad_churn_desc(READ_ONCE(port->sm_churn_actor_state)));
+                       seq_printf(seq, "Partner Churn State: %s\n",
+-                                 bond_3ad_churn_desc(port->sm_churn_partner_state));
++                                 bond_3ad_churn_desc(READ_ONCE(port->sm_churn_partner_state)));
+                       seq_printf(seq, "Actor Churned Count: %d\n",
+-                                 port->churn_actor_count);
++                                 READ_ONCE(port->churn_actor_count));
+                       seq_printf(seq, "Partner Churned Count: %d\n",
+-                                 port->churn_partner_count);
++                                 READ_ONCE(port->churn_partner_count));
+                       if (capable(CAP_NET_ADMIN)) {
+                               seq_puts(seq, "details actor lacp pdu:\n");
+-- 
+2.53.0
+
diff --git a/queue-7.0/devlink-release-nested-relation-on-devlink-free.patch b/queue-7.0/devlink-release-nested-relation-on-devlink-free.patch
new file mode 100644 (file)
index 0000000..5dcea78
--- /dev/null
@@ -0,0 +1,49 @@
+From 546906d54553b51809b4d8fdfb66359dd375b6af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 22:14:10 +0300
+Subject: devlink: Release nested relation on devlink free
+
+From: Mark Bloch <mbloch@nvidia.com>
+
+[ Upstream commit 3522b21fd7e1863d0734537737bd59f1b90d0190 ]
+
+devlink relation state is normally released from devl_unregister(), which
+calls devlink_rel_put(). This misses devlink instances that get a nested
+relation before registration and then fail probe before devl_register() is
+reached.
+
+That flow can happen for SFs. The child devlink gets linked to its
+parent before registration, then a later probe error calls devlink_free()
+directly. Since the instance was never registered, devl_unregister() is not
+called and devlink->rel is leaked.
+
+Release any pending relation from devlink_free() as well. The registered
+path is unchanged because devl_unregister() already clears devlink->rel
+before devlink_free() runs.
+
+Fixes: c137743bce02 ("devlink: introduce object and nested devlink relationship infra")
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://patch.msgid.link/20260528191411.3270532-1-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/devlink/core.c b/net/devlink/core.c
+index d8e509a669bf6c..998ba9eae9aed6 100644
+--- a/net/devlink/core.c
++++ b/net/devlink/core.c
+@@ -467,6 +467,8 @@ void devlink_free(struct devlink *devlink)
+ {
+       ASSERT_DEVLINK_NOT_REGISTERED(devlink);
++      devlink_rel_put(devlink);
++
+       WARN_ON(!list_empty(&devlink->trap_policer_list));
+       WARN_ON(!list_empty(&devlink->trap_group_list));
+       WARN_ON(!list_empty(&devlink->trap_list));
+-- 
+2.53.0
+
diff --git a/queue-7.0/dm-cache-policy-smq-check-allocation-under-invalidat.patch b/queue-7.0/dm-cache-policy-smq-check-allocation-under-invalidat.patch
new file mode 100644 (file)
index 0000000..393e95c
--- /dev/null
@@ -0,0 +1,71 @@
+From abe332d436a318357d723b15f8714c3a235c705b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:57:45 +0800
+Subject: dm cache policy smq: check allocation under invalidate lock
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit d3f0a606b9f278ece8a0df626ded9c4044071235 ]
+
+commit 2d1f7b65f5de ("dm cache policy smq: fix missing locks in
+invalidating cache blocks") added mq->lock around the destructive part of
+smq_invalidate_mapping(), but left the e->allocated check outside the
+critical section.
+
+That leaves a check-then-act race. Two concurrent invalidators can both
+observe e->allocated as true before either of them takes mq->lock. The
+first invalidator that acquires the lock removes the entry from the
+queues and hash table and then calls free_entry(), which clears
+e->allocated and puts the entry back on the free list. The second
+invalidator can then acquire mq->lock and continue with the stale result
+of the unlocked check.
+
+This can corrupt the SMQ queues or hash table by deleting an entry that
+is no longer on those structures. It can also hit the allocation check in
+free_entry() when the same entry is freed again.
+
+Move the allocation check under mq->lock so the predicate and the
+destructive operations are serialized by the same lock.
+
+Fixes: 2d1f7b65f5de ("dm cache policy smq: fix missing locks in invalidating cache blocks")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-policy-smq.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
+index dd77a93fd68d2d..1ae304c2f5737c 100644
+--- a/drivers/md/dm-cache-policy-smq.c
++++ b/drivers/md/dm-cache-policy-smq.c
+@@ -1590,18 +1590,22 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
+       struct smq_policy *mq = to_smq_policy(p);
+       struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+       unsigned long flags;
+-
+-      if (!e->allocated)
+-              return -ENODATA;
++      int r = 0;
+       spin_lock_irqsave(&mq->lock, flags);
++      if (!e->allocated) {
++              r = -ENODATA;
++              goto out;
++      }
+       // FIXME: what if this block has pending background work?
+       del_queue(mq, e);
+       h_remove(&mq->table, e);
+       free_entry(&mq->cache_alloc, e);
++
++out:
+       spin_unlock_irqrestore(&mq->lock, flags);
+-      return 0;
++      return r;
+ }
+ static uint32_t smq_get_hint(struct dm_cache_policy *p, dm_cblock_t cblock)
+-- 
+2.53.0
+
diff --git a/queue-7.0/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch b/queue-7.0/drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
new file mode 100644 (file)
index 0000000..3bc06b7
--- /dev/null
@@ -0,0 +1,53 @@
+From 03ac1513eb1348733fa0b65b0a7c708793211138 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2026 19:00:13 +0100
+Subject: drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
+
+From: Yicong Hui <yiconghui@gmail.com>
+
+[ Upstream commit ae0383e5a9a4b12d68c76c4769857def4665deff ]
+
+Fix the following W=1 kerneldoc warnings by adding the missing parameter
+descriptions for @phase0_identity and @nn_interpolation in
+dcss_scaler_filter_design() and @phase0_identity in
+dcss_scaler_gaussian_filter()
+
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design'
+Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design'
+
+Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ")
+Signed-off-by: Yicong Hui <yiconghui@gmail.com>
+Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
+Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+index 32c3f46b21daea..5c7f8d952ec1a1 100644
+--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
++++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+@@ -166,6 +166,7 @@ static int exp_approx_q(int x)
+  * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
+  * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
+  * @use_5_taps: indicates whether to use 5 taps or 7 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output filter coefficients
+  */
+ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
+@@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps,
+  * @src_length: length of input
+  * @dst_length: length of output
+  * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps
++ * @phase0_identity: whether to override phase 0 coefficients with identity filter
+  * @coef: output coefficients
++ * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter
+  */
+ static void dcss_scaler_filter_design(int src_length, int dst_length,
+                                     bool use_5_taps, bool phase0_identity,
+-- 
+2.53.0
+
diff --git a/queue-7.0/erofs-fix-use-after-free-on-sbi-sync_decompress.patch b/queue-7.0/erofs-fix-use-after-free-on-sbi-sync_decompress.patch
new file mode 100644 (file)
index 0000000..7de21f9
--- /dev/null
@@ -0,0 +1,66 @@
+From b9ef6c08fb95f04ad97d307394d3f4efbbf74bcd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:27:16 +0800
+Subject: erofs: fix use-after-free on sbi->sync_decompress
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+[ Upstream commit 1aee05e814d292064bf5fa15733741040cdc48ba ]
+
+z_erofs_decompress_kickoff() can race with filesystem unmount, causing
+a use-after-free on sbi->sync_decompress.
+
+When I/O completes, z_erofs_endio() calls z_erofs_decompress_kickoff()
+to queue z_erofs_decompressqueue_work() asynchronously. Then, after all
+folios are unlocked, unmount workflow can proceed and sbi will be freed
+before accessing to sbi->sync_decompress.
+
+Thread (unmount)        I/O completion        kworker
+                        queue_work
+                                              z_erofs_decompressqueue_work
+                                               (all folios are unlocked)
+cleanup_mnt
+ ..
+ erofs_kill_sb
+  erofs_sb_free
+   kfree(sbi)
+                        access sbi->sync_decompress  // UAF!!
+
+Fixes: 40452ffca3c1 ("erofs: add sysfs node to control sync decompression strategy")
+Reported-by: syzbot+52bae5c495dbe261a0bc@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=52bae5c495dbe261a0bc
+Reviewed-by: Chao Yu <chao@kernel.org>
+Reviewed-by: Jianan Huang <jnhuang95@gmail.com>
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/erofs/zdata.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index d7445e98312d80..50a5a1568370b0 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -1457,6 +1457,9 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+       if (atomic_add_return(bios, &io->pending_bios))
+               return;
+       if (z_erofs_in_atomic()) {
++              /* See `sync_decompress` in sysfs-fs-erofs for more details */
++              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
++                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+ #ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
+               struct kthread_worker *worker;
+@@ -1473,9 +1476,6 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
+ #else
+               queue_work(z_erofs_workqueue, &io->u.work);
+ #endif
+-              /* See `sync_decompress` in sysfs-fs-erofs for more details */
+-              if (sbi->sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO)
+-                      sbi->sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON;
+               return;
+       }
+       gfp_flag = memalloc_noio_save();
+-- 
+2.53.0
+
diff --git a/queue-7.0/fwctl-bnxt_en-move-common-definitions-to-include-lin.patch b/queue-7.0/fwctl-bnxt_en-move-common-definitions-to-include-lin.patch
new file mode 100644 (file)
index 0000000..b9d7e85
--- /dev/null
@@ -0,0 +1,185 @@
+From 2ddecb93293574d43586b459f5fbc119ed9cac43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Mar 2026 08:16:01 -0700
+Subject: fwctl/bnxt_en: Move common definitions to include/linux/bnxt/
+
+From: Pavan Chebbi <pavan.chebbi@broadcom.com>
+
+[ Upstream commit 7be18a1fa00eab5283b35c13e26c6b76fcaab9ce ]
+
+We have common definitions that are now going to be used
+by more than one component outside of bnxt (bnxt_re and
+fwctl)
+
+Move bnxt_ulp.h to include/linux/bnxt/ as ulp.h.
+
+Link: https://patch.msgid.link/r/20260314151605.932749-2-pavan.chebbi@broadcom.com
+Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Cc: linux-rdma@vger.kernel.org
+Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Stable-dep-of: b6197b386677 ("Reapply "bnxt_en: bring back rtnl_lock() in the bnxt_open() path"")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/bnxt_re/debugfs.c                         | 2 +-
+ drivers/infiniband/hw/bnxt_re/main.c                            | 2 +-
+ drivers/infiniband/hw/bnxt_re/qplib_fp.c                        | 2 +-
+ drivers/infiniband/hw/bnxt_re/qplib_res.h                       | 2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c                       | 2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c               | 2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c               | 2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c                 | 2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c                   | 2 +-
+ .../broadcom/bnxt/bnxt_ulp.h => include/linux/bnxt/ulp.h        | 0
+ 10 files changed, 9 insertions(+), 9 deletions(-)
+ rename drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h => include/linux/bnxt/ulp.h (100%)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
+index a2ad79c3bbd021..5fed2cf66be30a 100644
+--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
++++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
+@@ -10,8 +10,8 @@
+ #include <linux/pci.h>
+ #include <linux/seq_file.h>
+ #include <rdma/ib_addr.h>
++#include <linux/bnxt/ulp.h>
+-#include "bnxt_ulp.h"
+ #include "roce_hsi.h"
+ #include "qplib_res.h"
+ #include "qplib_sp.h"
+diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
+index b576f05e3b26b2..47afccddf55e57 100644
+--- a/drivers/infiniband/hw/bnxt_re/main.c
++++ b/drivers/infiniband/hw/bnxt_re/main.c
+@@ -55,8 +55,8 @@
+ #include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <linux/hashtable.h>
++#include <linux/bnxt/ulp.h>
+-#include "bnxt_ulp.h"
+ #include "roce_hsi.h"
+ #include "qplib_res.h"
+ #include "qplib_sp.h"
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+index 2d7932b3c492fa..b4c7b8f582ba9f 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+@@ -46,6 +46,7 @@
+ #include <linux/delay.h>
+ #include <linux/prefetch.h>
+ #include <linux/if_ether.h>
++#include <linux/bnxt/ulp.h>
+ #include <rdma/ib_mad.h>
+ #include "roce_hsi.h"
+@@ -55,7 +56,6 @@
+ #include "qplib_sp.h"
+ #include "qplib_fp.h"
+ #include <rdma/ib_addr.h>
+-#include "bnxt_ulp.h"
+ #include "bnxt_re.h"
+ #include "ib_verbs.h"
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
+index 9a5dcf97b6f440..0a4a03efeb0bab 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
+@@ -39,7 +39,7 @@
+ #ifndef __BNXT_QPLIB_RES_H__
+ #define __BNXT_QPLIB_RES_H__
+-#include "bnxt_ulp.h"
++#include <linux/bnxt/ulp.h>
+ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 3f775196ef8194..5d05084e32d93f 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -59,10 +59,10 @@
+ #include <net/netdev_rx_queue.h>
+ #include <linux/pci-tph.h>
+ #include <linux/bnxt/hsi.h>
++#include <linux/bnxt/ulp.h>
+ #include "bnxt.h"
+ #include "bnxt_hwrm.h"
+-#include "bnxt_ulp.h"
+ #include "bnxt_sriov.h"
+ #include "bnxt_ethtool.h"
+ #include "bnxt_dcb.h"
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+index 15de802bbac48e..230cd95d30a269 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+@@ -13,12 +13,12 @@
+ #include <net/devlink.h>
+ #include <net/netdev_lock.h>
+ #include <linux/bnxt/hsi.h>
++#include <linux/bnxt/ulp.h>
+ #include "bnxt.h"
+ #include "bnxt_hwrm.h"
+ #include "bnxt_vfr.h"
+ #include "bnxt_devlink.h"
+ #include "bnxt_ethtool.h"
+-#include "bnxt_ulp.h"
+ #include "bnxt_ptp.h"
+ #include "bnxt_coredump.h"
+ #include "bnxt_nvm_defs.h"
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index 0407aa1b3190e4..ef646a3463b1ec 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -27,9 +27,9 @@
+ #include <net/netdev_queues.h>
+ #include <net/netlink.h>
+ #include <linux/bnxt/hsi.h>
++#include <linux/bnxt/ulp.h>
+ #include "bnxt.h"
+ #include "bnxt_hwrm.h"
+-#include "bnxt_ulp.h"
+ #include "bnxt_xdp.h"
+ #include "bnxt_ptp.h"
+ #include "bnxt_ethtool.h"
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+index 7f9829287c4950..edcc002e4ca358 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+@@ -17,9 +17,9 @@
+ #include <linux/etherdevice.h>
+ #include <net/dcbnl.h>
+ #include <linux/bnxt/hsi.h>
++#include <linux/bnxt/ulp.h>
+ #include "bnxt.h"
+ #include "bnxt_hwrm.h"
+-#include "bnxt_ulp.h"
+ #include "bnxt_sriov.h"
+ #include "bnxt_vfr.h"
+ #include "bnxt_ethtool.h"
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+index e1e82a72cf1bb8..11ced44ead29b3 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+@@ -22,10 +22,10 @@
+ #include <linux/auxiliary_bus.h>
+ #include <net/netdev_lock.h>
+ #include <linux/bnxt/hsi.h>
++#include <linux/bnxt/ulp.h>
+ #include "bnxt.h"
+ #include "bnxt_hwrm.h"
+-#include "bnxt_ulp.h"
+ static DEFINE_IDA(bnxt_aux_dev_ids);
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h b/include/linux/bnxt/ulp.h
+similarity index 100%
+rename from drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
+rename to include/linux/bnxt/ulp.h
+-- 
+2.53.0
+
diff --git a/queue-7.0/fwctl-bnxt_en-refactor-aux-bus-functions-to-be-more-.patch b/queue-7.0/fwctl-bnxt_en-refactor-aux-bus-functions-to-be-more-.patch
new file mode 100644 (file)
index 0000000..e1849c8
--- /dev/null
@@ -0,0 +1,900 @@
+From ed63f826f1e2c50cdf03b171a3b233d7535c99b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Mar 2026 08:16:02 -0700
+Subject: fwctl/bnxt_en: Refactor aux bus functions to be more generic
+
+From: Pavan Chebbi <pavan.chebbi@broadcom.com>
+
+[ Upstream commit 2c7c85c8c7881d57c5fa1114f4b0dbd7fc53a36f ]
+
+Up until now there was only one auxiliary device that bnxt
+created and that was for RoCE driver. bnxt fwctl is also
+going to use an aux bus device that bnxt should create.
+This requires some nomenclature changes and refactoring of
+the existing bnxt aux dev functions.
+
+Convert 'aux_priv' and 'edev' members of struct bnxt into
+arrays where each element contains supported auxbus device's
+data. Move struct bnxt_aux_priv from bnxt.h to ulp.h because
+that is where it belongs. Make aux bus init/uninit/add/del
+functions more generic which will loop through all the aux
+device types. Make bnxt_ulp_start/stop functions (the only
+other common functions applicable to any aux device) loop
+through the aux devices to update their config and states.
+Make callers of bnxt_ulp_start() call it only when there
+are no errors.
+
+Also, as an improvement in code, bnxt_register_dev() can skip
+unnecessary dereferencing of edev from bp, instead use the
+edev pointer from the function parameter.
+
+Future patches will reuse these functions to add an aux bus
+device for fwctl.
+
+Link: https://patch.msgid.link/r/20260314151605.932749-3-pavan.chebbi@broadcom.com
+Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Stable-dep-of: b6197b386677 ("Reapply "bnxt_en: bring back rtnl_lock() in the bnxt_open() path"")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  47 ++-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  19 +-
+ .../net/ethernet/broadcom/bnxt/bnxt_devlink.c |   8 +-
+ .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c |   2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c | 339 +++++++++++-------
+ include/linux/bnxt/ulp.h                      |  25 +-
+ 6 files changed, 273 insertions(+), 167 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 5d05084e32d93f..86e45352cec105 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6896,7 +6896,8 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+ #endif
+       if ((bp->flags & BNXT_FLAG_STRIP_VLAN) || def_vlan)
+               req->flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
+-      if (vnic->vnic_id == BNXT_VNIC_DEFAULT && bnxt_ulp_registered(bp->edev))
++      if (vnic->vnic_id == BNXT_VNIC_DEFAULT &&
++          bnxt_ulp_registered(bp->edev[BNXT_AUXDEV_RDMA]))
+               req->flags |= cpu_to_le32(bnxt_get_roce_vnic_mode(bp));
+       return hwrm_req_send(bp, req);
+@@ -8031,6 +8032,7 @@ static int bnxt_get_avail_msix(struct bnxt *bp, int num);
+ static int __bnxt_reserve_rings(struct bnxt *bp)
+ {
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
+       struct bnxt_hw_rings hwr = {0};
+       int rx_rings, old_rx_rings, rc;
+       int cp = bp->cp_nr_rings;
+@@ -8041,7 +8043,7 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
+       if (!bnxt_need_reserve_rings(bp))
+               return 0;
+-      if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(bp->edev)) {
++      if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(edev)) {
+               ulp_msix = bnxt_get_avail_msix(bp, bp->ulp_num_msix_want);
+               if (!ulp_msix)
+                       bnxt_set_ulp_stat_ctxs(bp, 0);
+@@ -8094,8 +8096,7 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
+       }
+       rx_rings = min_t(int, rx_rings, hwr.grp);
+       hwr.cp = min_t(int, hwr.cp, bp->cp_nr_rings);
+-      if (bnxt_ulp_registered(bp->edev) &&
+-          hwr.stat > bnxt_get_ulp_stat_ctxs(bp))
++      if (bnxt_ulp_registered(edev) && hwr.stat > bnxt_get_ulp_stat_ctxs(bp))
+               hwr.stat -= bnxt_get_ulp_stat_ctxs(bp);
+       hwr.cp = min_t(int, hwr.cp, hwr.stat);
+       rc = bnxt_trim_rings(bp, &rx_rings, &hwr.tx, hwr.cp, sh);
+@@ -8139,7 +8140,7 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
+           !netif_is_rxfh_configured(bp->dev))
+               bnxt_set_dflt_rss_indir_tbl(bp, NULL);
+-      if (!bnxt_ulp_registered(bp->edev) && BNXT_NEW_RM(bp)) {
++      if (!bnxt_ulp_registered(edev) && BNXT_NEW_RM(bp)) {
+               int resv_msix, resv_ctx, ulp_ctxs;
+               struct bnxt_hw_resc *hw_resc;
+@@ -11496,6 +11497,7 @@ static void bnxt_clear_int_mode(struct bnxt *bp)
+ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
+ {
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
+       bool irq_cleared = false;
+       bool irq_change = false;
+       int tcs = bp->num_tc;
+@@ -11505,7 +11507,7 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
+       if (!bnxt_need_reserve_rings(bp))
+               return 0;
+-      if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(bp->edev)) {
++      if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(edev)) {
+               int ulp_msix = bnxt_get_avail_msix(bp, bp->ulp_num_msix_want);
+               if (ulp_msix > bp->ulp_num_msix_want)
+@@ -14604,7 +14606,7 @@ static void bnxt_fw_echo_reply(struct bnxt *bp)
+ static void bnxt_ulp_restart(struct bnxt *bp)
+ {
+       bnxt_ulp_stop(bp);
+-      bnxt_ulp_start(bp, 0);
++      bnxt_ulp_start(bp);
+ }
+ static void bnxt_sp_task(struct work_struct *work)
+@@ -14761,7 +14763,7 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
+               hwr.cp_p5 = hwr.tx + rx;
+       rc = bnxt_hwrm_check_rings(bp, &hwr);
+       if (!rc && pci_msix_can_alloc_dyn(bp->pdev)) {
+-              if (!bnxt_ulp_registered(bp->edev)) {
++              if (!bnxt_ulp_registered(bp->edev[BNXT_AUXDEV_RDMA])) {
+                       hwr.cp += bnxt_get_ulp_msix_num(bp);
+                       hwr.cp = min_t(int, hwr.cp, bnxt_get_max_func_irqs(bp));
+               }
+@@ -15281,7 +15283,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
+                       bnxt_dl_health_fw_status_update(bp, true);
+               }
+               netdev_unlock(bp->dev);
+-              bnxt_ulp_start(bp, 0);
++              bnxt_ulp_start(bp);
+               bnxt_reenable_sriov(bp);
+               netdev_lock(bp->dev);
+               bnxt_vf_reps_alloc(bp);
+@@ -15303,7 +15305,8 @@ static void bnxt_fw_reset_task(struct work_struct *work)
+       bnxt_fw_reset_abort(bp, rc);
+       netdev_unlock(bp->dev);
+ ulp_start:
+-      bnxt_ulp_start(bp, rc);
++      if (!rc)
++              bnxt_ulp_start(bp);
+ }
+ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
+@@ -16344,12 +16347,13 @@ static void bnxt_remove_one(struct pci_dev *pdev)
+       if (BNXT_PF(bp))
+               __bnxt_sriov_disable(bp);
+-      bnxt_rdma_aux_device_del(bp);
++      bnxt_aux_devices_del(bp);
+       unregister_netdev(dev);
+       bnxt_ptp_clear(bp);
+-      bnxt_rdma_aux_device_uninit(bp);
++      bnxt_aux_devices_uninit(bp);
++      bnxt_auxdev_id_free(bp, bp->auxdev_id);
+       bnxt_free_l2_filters(bp, true);
+       bnxt_free_ntp_fltrs(bp, true);
+@@ -16946,7 +16950,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+       bnxt_set_tpa_flags(bp);
+       bnxt_init_ring_params(bp);
+       bnxt_set_ring_params(bp);
+-      bnxt_rdma_aux_device_init(bp);
++      mutex_init(&bp->auxdev_lock);
++      if (!bnxt_auxdev_id_alloc(bp))
++              bnxt_aux_devices_init(bp);
+       rc = bnxt_set_dflt_rings(bp, true);
+       if (rc) {
+               if (BNXT_VF(bp) && rc == -ENODEV) {
+@@ -17011,7 +17017,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+       bnxt_dl_fw_reporters_create(bp);
+-      bnxt_rdma_aux_device_add(bp);
++      bnxt_aux_devices_add(bp);
+       bnxt_print_device_info(bp);
+@@ -17019,7 +17025,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+       return 0;
+ init_err_cleanup:
+-      bnxt_rdma_aux_device_uninit(bp);
++      bnxt_aux_devices_uninit(bp);
++      bnxt_auxdev_id_free(bp, bp->auxdev_id);
+       bnxt_dl_unregister(bp);
+ init_err_dl:
+       bnxt_shutdown_tc(bp);
+@@ -17153,9 +17160,10 @@ static int bnxt_resume(struct device *device)
+ resume_exit:
+       netdev_unlock(bp->dev);
+-      bnxt_ulp_start(bp, rc);
+-      if (!rc)
++      if (!rc) {
++              bnxt_ulp_start(bp);
+               bnxt_reenable_sriov(bp);
++      }
+       return rc;
+ }
+@@ -17335,9 +17343,10 @@ static void bnxt_io_resume(struct pci_dev *pdev)
+               netif_device_attach(netdev);
+       netdev_unlock(netdev);
+-      bnxt_ulp_start(bp, err);
+-      if (!err)
++      if (!err) {
++              bnxt_ulp_start(bp);
+               bnxt_reenable_sriov(bp);
++      }
+ }
+ static const struct pci_error_handlers bnxt_err_handler = {
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 4bc7f7aeaab378..8899ef51bdcfec 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -24,12 +24,12 @@
+ #include <linux/interrupt.h>
+ #include <linux/rhashtable.h>
+ #include <linux/crash_dump.h>
+-#include <linux/auxiliary_bus.h>
+ #include <net/devlink.h>
+ #include <net/dst_metadata.h>
+ #include <net/xdp.h>
+ #include <linux/dim.h>
+ #include <linux/io-64-nonatomic-lo-hi.h>
++#include <linux/bnxt/ulp.h>
+ #ifdef CONFIG_TEE_BNXT_FW
+ #include <linux/firmware/broadcom/tee_bnxt_fw.h>
+ #endif
+@@ -2085,12 +2085,6 @@ struct bnxt_fw_health {
+ #define BNXT_FW_IF_RETRY              10
+ #define BNXT_FW_SLOT_RESET_RETRY      4
+-struct bnxt_aux_priv {
+-      struct auxiliary_device aux_dev;
+-      struct bnxt_en_dev *edev;
+-      int id;
+-};
+-
+ enum board_idx {
+       BCM57301,
+       BCM57302,
+@@ -2350,8 +2344,8 @@ struct bnxt {
+ #define BNXT_CHIP_P5_AND_MINUS(bp)            \
+       (BNXT_CHIP_P3(bp) || BNXT_CHIP_P4(bp) || BNXT_CHIP_P5(bp))
+-      struct bnxt_aux_priv    *aux_priv;
+-      struct bnxt_en_dev      *edev;
++      struct bnxt_aux_priv    *aux_priv[__BNXT_AUXDEV_MAX];
++      struct bnxt_en_dev      *edev[__BNXT_AUXDEV_MAX];
+       struct bnxt_napi        **bnapi;
+@@ -2763,6 +2757,13 @@ struct bnxt {
+       struct bnxt_ctx_pg_info *fw_crash_mem;
+       u32                     fw_crash_len;
+       struct bnxt_bs_trace_info bs_trace[BNXT_TRACE_MAX];
++      int                     auxdev_id;
++      /* synchronize validity checks of available aux devices */
++      struct mutex            auxdev_lock;
++      u8                      auxdev_state[__BNXT_AUXDEV_MAX];
++#define       BNXT_ADEV_STATE_NONE    0
++#define       BNXT_ADEV_STATE_INIT    1
++#define       BNXT_ADEV_STATE_ADD     2
+ };
+ #define BNXT_NUM_RX_RING_STATS                        8
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+index 230cd95d30a269..835f2b413931c2 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+@@ -440,13 +440,13 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
+                                          "reload is unsupported while VFs are allocated or being configured");
+                       netdev_unlock(bp->dev);
+                       rtnl_unlock();
+-                      bnxt_ulp_start(bp, 0);
++                      bnxt_ulp_start(bp);
+                       return -EOPNOTSUPP;
+               }
+               if (bp->dev->reg_state == NETREG_UNREGISTERED) {
+                       netdev_unlock(bp->dev);
+                       rtnl_unlock();
+-                      bnxt_ulp_start(bp, 0);
++                      bnxt_ulp_start(bp);
+                       return -ENODEV;
+               }
+               if (netif_running(bp->dev))
+@@ -578,8 +578,8 @@ static int bnxt_dl_reload_up(struct devlink *dl, enum devlink_reload_action acti
+       }
+       netdev_unlock(bp->dev);
+       rtnl_unlock();
+-      if (action == DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
+-              bnxt_ulp_start(bp, rc);
++      if (!rc && action == DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
++              bnxt_ulp_start(bp);
+       return rc;
+ }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index ef646a3463b1ec..6596cd7447526e 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -5209,7 +5209,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
+       memset(buf, 0, sizeof(u64) * bp->num_tests);
+       if (etest->flags & ETH_TEST_FL_OFFLINE &&
+-          bnxt_ulp_registered(bp->edev)) {
++          bnxt_ulp_registered(bp->edev[BNXT_AUXDEV_RDMA])) {
+               etest->flags |= ETH_TEST_FL_FAILED;
+               netdev_warn(dev, "Offline tests cannot be run with RoCE driver loaded\n");
+               return;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+index 11ced44ead29b3..3705ef3a75c9ec 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+@@ -29,9 +29,32 @@
+ static DEFINE_IDA(bnxt_aux_dev_ids);
++struct bnxt_aux_device {
++      const char *name;
++};
++
++static void bnxt_auxdev_set_state(struct bnxt *bp, int idx, int state)
++{
++      bp->auxdev_state[idx] = state;
++}
++
++static bool bnxt_auxdev_is_init(struct bnxt *bp, int idx)
++{
++      return (bp->auxdev_state[idx] == BNXT_ADEV_STATE_INIT);
++}
++
++static bool bnxt_auxdev_is_active(struct bnxt *bp, int idx)
++{
++      return (bp->auxdev_state[idx] == BNXT_ADEV_STATE_ADD);
++}
++
++static struct bnxt_aux_device bnxt_aux_devices[__BNXT_AUXDEV_MAX] = {{
++      .name           = "rdma",
++}};
++
+ static void bnxt_fill_msix_vecs(struct bnxt *bp, struct bnxt_msix_entry *ent)
+ {
+-      struct bnxt_en_dev *edev = bp->edev;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
+       int num_msix, i;
+       if (!edev->ulp_tbl->msix_requested) {
+@@ -51,61 +74,75 @@ static void bnxt_fill_msix_vecs(struct bnxt *bp, struct bnxt_msix_entry *ent)
+ int bnxt_get_ulp_msix_num(struct bnxt *bp)
+ {
+-      if (bp->edev)
+-              return bp->edev->ulp_num_msix_vec;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (edev)
++              return edev->ulp_num_msix_vec;
+       return 0;
+ }
+ void bnxt_set_ulp_msix_num(struct bnxt *bp, int num)
+ {
+-      if (bp->edev)
+-              bp->edev->ulp_num_msix_vec = num;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (edev)
++              edev->ulp_num_msix_vec = num;
+ }
+ int bnxt_get_ulp_msix_num_in_use(struct bnxt *bp)
+ {
+-      if (bnxt_ulp_registered(bp->edev))
+-              return bp->edev->ulp_num_msix_vec;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (bnxt_ulp_registered(edev))
++              return edev->ulp_num_msix_vec;
+       return 0;
+ }
+ int bnxt_get_ulp_stat_ctxs(struct bnxt *bp)
+ {
+-      if (bp->edev)
+-              return bp->edev->ulp_num_ctxs;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (edev)
++              return edev->ulp_num_ctxs;
+       return 0;
+ }
+ void bnxt_set_ulp_stat_ctxs(struct bnxt *bp, int num_ulp_ctx)
+ {
+-      if (bp->edev)
+-              bp->edev->ulp_num_ctxs = num_ulp_ctx;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (edev)
++              edev->ulp_num_ctxs = num_ulp_ctx;
+ }
+ int bnxt_get_ulp_stat_ctxs_in_use(struct bnxt *bp)
+ {
+-      if (bnxt_ulp_registered(bp->edev))
+-              return bp->edev->ulp_num_ctxs;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (bnxt_ulp_registered(edev))
++              return edev->ulp_num_ctxs;
+       return 0;
+ }
+ void bnxt_set_dflt_ulp_stat_ctxs(struct bnxt *bp)
+ {
+-      if (bp->edev) {
+-              bp->edev->ulp_num_ctxs = BNXT_MIN_ROCE_STAT_CTXS;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
++
++      if (edev) {
++              edev->ulp_num_ctxs = BNXT_MIN_ROCE_STAT_CTXS;
+               /* Reserve one additional stat_ctx for PF0 (except
+                * on 1-port NICs) as it also creates one stat_ctx
+                * for PF1 in case of RoCE bonding.
+                */
+               if (BNXT_PF(bp) && !bp->pf.port_id &&
+                   bp->port_count > 1)
+-                      bp->edev->ulp_num_ctxs++;
++                      edev->ulp_num_ctxs++;
+               /* Reserve one additional stat_ctx when the device is capable
+                * of supporting port mirroring on RDMA device.
+                */
+               if (BNXT_MIRROR_ON_ROCE_CAP(bp))
+-                      bp->edev->ulp_num_ctxs++;
++                      edev->ulp_num_ctxs++;
+       }
+ }
+@@ -141,7 +178,7 @@ int bnxt_register_dev(struct bnxt_en_dev *edev,
+       edev->ulp_tbl->msix_requested = bnxt_get_ulp_msix_num(bp);
+-      bnxt_fill_msix_vecs(bp, bp->edev->msix_entries);
++      bnxt_fill_msix_vecs(bp, edev->msix_entries);
+ exit:
+       mutex_unlock(&edev->en_dev_lock);
+       netdev_unlock(dev);
+@@ -227,20 +264,27 @@ EXPORT_SYMBOL(bnxt_send_msg);
+ void bnxt_ulp_stop(struct bnxt *bp)
+ {
+-      struct bnxt_aux_priv *aux_priv = bp->aux_priv;
+-      struct bnxt_en_dev *edev = bp->edev;
++      int i;
+-      if (!edev)
+-              return;
+-
+-      mutex_lock(&edev->en_dev_lock);
+-      if (!bnxt_ulp_registered(edev) ||
+-          (edev->flags & BNXT_EN_FLAG_ULP_STOPPED))
+-              goto ulp_stop_exit;
+-
+-      edev->flags |= BNXT_EN_FLAG_ULP_STOPPED;
+-      if (aux_priv) {
++      mutex_lock(&bp->auxdev_lock);
++      for (i = 0; i < __BNXT_AUXDEV_MAX; i++) {
++              struct bnxt_aux_priv *aux_priv;
+               struct auxiliary_device *adev;
++              struct bnxt_en_dev *edev;
++
++              if (!bnxt_auxdev_is_active(bp, i))
++                      continue;
++
++              aux_priv = bp->aux_priv[i];
++              edev = bp->edev[i];
++              mutex_lock(&edev->en_dev_lock);
++              if (!bnxt_ulp_registered(edev) ||
++                  (edev->flags & BNXT_EN_FLAG_ULP_STOPPED)) {
++                      mutex_unlock(&edev->en_dev_lock);
++                      continue;
++              }
++
++              edev->flags |= BNXT_EN_FLAG_ULP_STOPPED;
+               adev = &aux_priv->aux_dev;
+               if (adev->dev.driver) {
+@@ -251,29 +295,35 @@ void bnxt_ulp_stop(struct bnxt *bp)
+                       edev->en_state = bp->state;
+                       adrv->suspend(adev, pm);
+               }
++              mutex_unlock(&edev->en_dev_lock);
+       }
+-ulp_stop_exit:
+-      mutex_unlock(&edev->en_dev_lock);
++      mutex_unlock(&bp->auxdev_lock);
+ }
+-void bnxt_ulp_start(struct bnxt *bp, int err)
++void bnxt_ulp_start(struct bnxt *bp)
+ {
+-      struct bnxt_aux_priv *aux_priv = bp->aux_priv;
+-      struct bnxt_en_dev *edev = bp->edev;
++      int i;
+-      if (!edev || err)
+-              return;
++      mutex_lock(&bp->auxdev_lock);
++      for (i = 0; i < __BNXT_AUXDEV_MAX; i++) {
++              struct bnxt_aux_priv *aux_priv;
++              struct auxiliary_device *adev;
++              struct bnxt_en_dev *edev;
+-      mutex_lock(&edev->en_dev_lock);
+-      if (!bnxt_ulp_registered(edev) ||
+-          !(edev->flags & BNXT_EN_FLAG_ULP_STOPPED))
+-              goto ulp_start_exit;
++              if (!bnxt_auxdev_is_active(bp, i))
++                      continue;
+-      if (edev->ulp_tbl->msix_requested)
+-              bnxt_fill_msix_vecs(bp, edev->msix_entries);
++              aux_priv = bp->aux_priv[i];
++              edev = bp->edev[i];
++              mutex_lock(&edev->en_dev_lock);
++              if (!bnxt_ulp_registered(edev) ||
++                  !(edev->flags & BNXT_EN_FLAG_ULP_STOPPED)) {
++                      goto clear_flag_continue;
++              }
++
++              if (edev->ulp_tbl->msix_requested)
++                      bnxt_fill_msix_vecs(bp, edev->msix_entries);
+-      if (aux_priv) {
+-              struct auxiliary_device *adev;
+               adev = &aux_priv->aux_dev;
+               if (adev->dev.driver) {
+@@ -283,22 +333,23 @@ void bnxt_ulp_start(struct bnxt *bp, int err)
+                       edev->en_state = bp->state;
+                       adrv->resume(adev);
+               }
++clear_flag_continue:
++              edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED;
++              mutex_unlock(&edev->en_dev_lock);
+       }
+-ulp_start_exit:
+-      edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED;
+-      mutex_unlock(&edev->en_dev_lock);
++      mutex_unlock(&bp->auxdev_lock);
+ }
+ void bnxt_ulp_irq_stop(struct bnxt *bp)
+ {
+-      struct bnxt_en_dev *edev = bp->edev;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
+       struct bnxt_ulp_ops *ops;
+       bool reset = false;
+       if (!edev)
+               return;
+-      if (bnxt_ulp_registered(bp->edev)) {
++      if (bnxt_ulp_registered(edev)) {
+               struct bnxt_ulp *ulp = edev->ulp_tbl;
+               if (!ulp->msix_requested)
+@@ -315,13 +366,13 @@ void bnxt_ulp_irq_stop(struct bnxt *bp)
+ void bnxt_ulp_irq_restart(struct bnxt *bp, int err)
+ {
+-      struct bnxt_en_dev *edev = bp->edev;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
+       struct bnxt_ulp_ops *ops;
+       if (!edev)
+               return;
+-      if (bnxt_ulp_registered(bp->edev)) {
++      if (bnxt_ulp_registered(edev)) {
+               struct bnxt_ulp *ulp = edev->ulp_tbl;
+               struct bnxt_msix_entry *ent = NULL;
+@@ -346,7 +397,7 @@ void bnxt_ulp_irq_restart(struct bnxt *bp, int err)
+ void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl)
+ {
+       u16 event_id = le16_to_cpu(cmpl->event_id);
+-      struct bnxt_en_dev *edev = bp->edev;
++      struct bnxt_en_dev *edev = bp->edev[BNXT_AUXDEV_RDMA];
+       struct bnxt_ulp_ops *ops;
+       struct bnxt_ulp *ulp;
+@@ -387,18 +438,21 @@ void bnxt_register_async_events(struct bnxt_en_dev *edev,
+ }
+ EXPORT_SYMBOL(bnxt_register_async_events);
+-void bnxt_rdma_aux_device_uninit(struct bnxt *bp)
++void bnxt_aux_devices_uninit(struct bnxt *bp)
+ {
+       struct bnxt_aux_priv *aux_priv;
+       struct auxiliary_device *adev;
+-
+-      /* Skip if no auxiliary device init was done. */
+-      if (!bp->aux_priv)
+-              return;
+-
+-      aux_priv = bp->aux_priv;
+-      adev = &aux_priv->aux_dev;
+-      auxiliary_device_uninit(adev);
++      int idx;
++
++      mutex_lock(&bp->auxdev_lock);
++      for (idx = 0; idx < __BNXT_AUXDEV_MAX; idx++) {
++              if (bnxt_auxdev_is_init(bp, idx)) {
++                      aux_priv = bp->aux_priv[idx];
++                      adev = &aux_priv->aux_dev;
++                      auxiliary_device_uninit(adev);
++              }
++      }
++      mutex_unlock(&bp->auxdev_lock);
+ }
+ static void bnxt_aux_dev_release(struct device *dev)
+@@ -407,20 +461,25 @@ static void bnxt_aux_dev_release(struct device *dev)
+               container_of(dev, struct bnxt_aux_priv, aux_dev.dev);
+       struct bnxt *bp = netdev_priv(aux_priv->edev->net);
+-      ida_free(&bnxt_aux_dev_ids, aux_priv->id);
+       kfree(aux_priv->edev->ulp_tbl);
+-      bp->edev = NULL;
++      bp->edev[aux_priv->id] = NULL;
+       kfree(aux_priv->edev);
++      bp->aux_priv[aux_priv->id] = NULL;
+       kfree(aux_priv);
+-      bp->aux_priv = NULL;
+ }
+-void bnxt_rdma_aux_device_del(struct bnxt *bp)
++void bnxt_aux_devices_del(struct bnxt *bp)
+ {
+-      if (!bp->edev)
+-              return;
++      int idx;
+-      auxiliary_device_delete(&bp->aux_priv->aux_dev);
++      mutex_lock(&bp->auxdev_lock);
++      for (idx = 0; idx < __BNXT_AUXDEV_MAX; idx++) {
++              if (bnxt_auxdev_is_active(bp, idx)) {
++                      auxiliary_device_delete(&bp->aux_priv[idx]->aux_dev);
++                      bnxt_auxdev_set_state(bp, idx, BNXT_ADEV_STATE_INIT);
++              }
++      }
++      mutex_unlock(&bp->auxdev_lock);
+ }
+ static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
+@@ -450,83 +509,105 @@ static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
+       edev->bar0 = bp->bar0;
+ }
+-void bnxt_rdma_aux_device_add(struct bnxt *bp)
++void bnxt_aux_devices_add(struct bnxt *bp)
+ {
+       struct auxiliary_device *aux_dev;
+-      int rc;
+-
+-      if (!bp->edev)
+-              return;
+-
+-      aux_dev = &bp->aux_priv->aux_dev;
+-      rc = auxiliary_device_add(aux_dev);
+-      if (rc) {
+-              netdev_warn(bp->dev, "Failed to add auxiliary device for ROCE\n");
+-              auxiliary_device_uninit(aux_dev);
+-              bp->flags &= ~BNXT_FLAG_ROCE_CAP;
++      int rc, idx;
++
++      mutex_lock(&bp->auxdev_lock);
++      for (idx = 0; idx < __BNXT_AUXDEV_MAX; idx++) {
++              if (bnxt_auxdev_is_init(bp, idx)) {
++                      aux_dev = &bp->aux_priv[idx]->aux_dev;
++                      rc = auxiliary_device_add(aux_dev);
++                      if (rc) {
++                              netdev_warn(bp->dev, "Failed to add auxiliary device for ROCE\n");
++                              auxiliary_device_uninit(aux_dev);
++                              if (idx == BNXT_AUXDEV_RDMA)
++                                      bp->flags &= ~BNXT_FLAG_ROCE_CAP;
++                              continue;
++                      }
++                      bnxt_auxdev_set_state(bp, idx, BNXT_ADEV_STATE_ADD);
++              }
+       }
++      mutex_unlock(&bp->auxdev_lock);
+ }
+-void bnxt_rdma_aux_device_init(struct bnxt *bp)
++void bnxt_aux_devices_init(struct bnxt *bp)
+ {
+       struct auxiliary_device *aux_dev;
+       struct bnxt_aux_priv *aux_priv;
+       struct bnxt_en_dev *edev;
+       struct bnxt_ulp *ulp;
+-      int rc;
++      int rc, idx;
++
++      mutex_lock(&bp->auxdev_lock);
++      for (idx = 0; idx < __BNXT_AUXDEV_MAX; idx++) {
++              bnxt_auxdev_set_state(bp, idx, BNXT_ADEV_STATE_NONE);
++
++              if (idx == BNXT_AUXDEV_RDMA &&
++                  !(bp->flags & BNXT_FLAG_ROCE_CAP))
++                      continue;
++
++              aux_priv = kzalloc_obj(*aux_priv);
++              if (!aux_priv)
++                      goto next_auxdev;
++
++              aux_dev = &aux_priv->aux_dev;
++              aux_dev->id = bp->auxdev_id;
++              aux_dev->name = bnxt_aux_devices[idx].name;
++              aux_dev->dev.parent = &bp->pdev->dev;
++              aux_dev->dev.release = bnxt_aux_dev_release;
++
++              rc = auxiliary_device_init(aux_dev);
++              if (rc) {
++                      kfree(aux_priv);
++                      goto next_auxdev;
++              }
++              bp->aux_priv[idx] = aux_priv;
+-      if (!(bp->flags & BNXT_FLAG_ROCE_CAP))
+-              return;
++              /* From this point, all cleanup will happen via the .release
++               * callback & any error unwinding will need to include a call
++               * to auxiliary_device_uninit.
++               */
++              edev = kzalloc_obj(*edev);
++              if (!edev)
++                      goto aux_dev_uninit;
+-      aux_priv = kzalloc_obj(*bp->aux_priv);
+-      if (!aux_priv)
+-              goto exit;
++              aux_priv->edev = edev;
++              bnxt_set_edev_info(edev, bp);
+-      aux_priv->id = ida_alloc(&bnxt_aux_dev_ids, GFP_KERNEL);
+-      if (aux_priv->id < 0) {
+-              netdev_warn(bp->dev,
+-                          "ida alloc failed for ROCE auxiliary device\n");
+-              kfree(aux_priv);
+-              goto exit;
+-      }
++              ulp = kzalloc_obj(*ulp);
++              if (!ulp)
++                      goto aux_dev_uninit;
+-      aux_dev = &aux_priv->aux_dev;
+-      aux_dev->id = aux_priv->id;
+-      aux_dev->name = "rdma";
+-      aux_dev->dev.parent = &bp->pdev->dev;
+-      aux_dev->dev.release = bnxt_aux_dev_release;
++              edev->ulp_tbl = ulp;
++              bp->edev[idx] = edev;
++              if (idx == BNXT_AUXDEV_RDMA)
++                      bp->ulp_num_msix_want = bnxt_set_dflt_ulp_msix(bp);
++              aux_priv->id = idx;
++              bnxt_auxdev_set_state(bp, idx, BNXT_ADEV_STATE_INIT);
+-      rc = auxiliary_device_init(aux_dev);
+-      if (rc) {
+-              ida_free(&bnxt_aux_dev_ids, aux_priv->id);
+-              kfree(aux_priv);
+-              goto exit;
++              continue;
++aux_dev_uninit:
++              auxiliary_device_uninit(aux_dev);
++next_auxdev:
++              if (idx == BNXT_AUXDEV_RDMA)
++                      bp->flags &= ~BNXT_FLAG_ROCE_CAP;
+       }
+-      bp->aux_priv = aux_priv;
+-
+-      /* From this point, all cleanup will happen via the .release callback &
+-       * any error unwinding will need to include a call to
+-       * auxiliary_device_uninit.
+-       */
+-      edev = kzalloc_obj(*edev);
+-      if (!edev)
+-              goto aux_dev_uninit;
+-
+-      aux_priv->edev = edev;
+-
+-      ulp = kzalloc_obj(*ulp);
+-      if (!ulp)
+-              goto aux_dev_uninit;
++      mutex_unlock(&bp->auxdev_lock);
++}
+-      edev->ulp_tbl = ulp;
+-      bp->edev = edev;
+-      bnxt_set_edev_info(edev, bp);
+-      bp->ulp_num_msix_want = bnxt_set_dflt_ulp_msix(bp);
++int bnxt_auxdev_id_alloc(struct bnxt *bp)
++{
++      bp->auxdev_id = ida_alloc(&bnxt_aux_dev_ids, GFP_KERNEL);
++      if (bp->auxdev_id < 0)
++              return bp->auxdev_id;
+-      return;
++      return 0;
++}
+-aux_dev_uninit:
+-      auxiliary_device_uninit(aux_dev);
+-exit:
+-      bp->flags &= ~BNXT_FLAG_ROCE_CAP;
++void bnxt_auxdev_id_free(struct bnxt *bp, int id)
++{
++      if (bp->auxdev_id >= 0)
++              ida_free(&bnxt_aux_dev_ids, id);
+ }
+diff --git a/include/linux/bnxt/ulp.h b/include/linux/bnxt/ulp.h
+index 3c5b8a53f71507..1a4643c46f86fb 100644
+--- a/include/linux/bnxt/ulp.h
++++ b/include/linux/bnxt/ulp.h
+@@ -10,6 +10,8 @@
+ #ifndef BNXT_ULP_H
+ #define BNXT_ULP_H
++#include <linux/auxiliary_bus.h>
++
+ #define BNXT_MIN_ROCE_CP_RINGS        2
+ #define BNXT_MIN_ROCE_STAT_CTXS       1
+@@ -20,6 +22,17 @@
+ struct hwrm_async_event_cmpl;
+ struct bnxt;
++enum bnxt_auxdev_type {
++      BNXT_AUXDEV_RDMA = 0,
++      __BNXT_AUXDEV_MAX
++};
++
++struct bnxt_aux_priv {
++      struct auxiliary_device aux_dev;
++      struct bnxt_en_dev *edev;
++      int id;
++};
++
+ struct bnxt_msix_entry {
+       u32     vector;
+       u32     ring_idx;
+@@ -110,19 +123,21 @@ void bnxt_set_ulp_stat_ctxs(struct bnxt *bp, int num_ctxs);
+ int bnxt_get_ulp_stat_ctxs_in_use(struct bnxt *bp);
+ void bnxt_set_dflt_ulp_stat_ctxs(struct bnxt *bp);
+ void bnxt_ulp_stop(struct bnxt *bp);
+-void bnxt_ulp_start(struct bnxt *bp, int err);
++void bnxt_ulp_start(struct bnxt *bp);
+ void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
+ void bnxt_ulp_irq_stop(struct bnxt *bp);
+ void bnxt_ulp_irq_restart(struct bnxt *bp, int err);
+ void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl);
+-void bnxt_rdma_aux_device_uninit(struct bnxt *bp);
+-void bnxt_rdma_aux_device_del(struct bnxt *bp);
+-void bnxt_rdma_aux_device_add(struct bnxt *bp);
+-void bnxt_rdma_aux_device_init(struct bnxt *bp);
++void bnxt_aux_devices_uninit(struct bnxt *bp);
++void bnxt_aux_devices_del(struct bnxt *bp);
++void bnxt_aux_devices_add(struct bnxt *bp);
++void bnxt_aux_devices_init(struct bnxt *bp);
+ int bnxt_register_dev(struct bnxt_en_dev *edev, struct bnxt_ulp_ops *ulp_ops,
+                     void *handle);
+ void bnxt_unregister_dev(struct bnxt_en_dev *edev);
+ int bnxt_send_msg(struct bnxt_en_dev *edev, struct bnxt_fw_msg *fw_msg);
+ void bnxt_register_async_events(struct bnxt_en_dev *edev,
+                               unsigned long *events_bmap, u16 max_id);
++int bnxt_auxdev_id_alloc(struct bnxt *bp);
++void bnxt_auxdev_id_free(struct bnxt *bp, int id);
+ #endif
+-- 
+2.53.0
+
diff --git a/queue-7.0/geneve-fix-length-used-in-gro-hint-udp-checksum-adju.patch b/queue-7.0/geneve-fix-length-used-in-gro-hint-udp-checksum-adju.patch
new file mode 100644 (file)
index 0000000..7ac23c6
--- /dev/null
@@ -0,0 +1,42 @@
+From 4a4a1490a5ea19986f17bd7a844c4757c1c1e95e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 16:47:00 +0200
+Subject: geneve: fix length used in GRO hint UDP checksum adjustment
+
+From: Antoine Tenart <atenart@kernel.org>
+
+[ Upstream commit 1231623fd3b5aa6b41cce799ffb0d82e10914be4 ]
+
+In geneve_post_decap_hint the length used for adjusting the UDP checksum
+should be 'skb->len - gro_hint->nested_tp_offset' (UDP length) instead
+of 'skb->len - gro_hint->nested_nh_offset' (IP length).
+
+Fixes: fd0dd796576e ("geneve: use GRO hint option in the RX path")
+Cc: Paolo Abeni <pabeni@redhat.com>
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260521131436.748832-1-jhs%40mojatatu.com
+Signed-off-by: Antoine Tenart <atenart@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260529144713.780938-1-atenart@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/geneve.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 01cdd06102e0db..8ea9482d52e538 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -633,7 +633,7 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb,
+       uh = udp_hdr(skb);
+       uh->len = htons(skb->len - gro_hint->nested_tp_offset);
+       if (uh->check) {
+-              len = skb->len - gro_hint->nested_nh_offset;
++              len = skb->len - gro_hint->nested_tp_offset;
+               skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM;
+               if (gro_hint->nested_is_v6)
+                       uh->check = ~udp_v6_check(len, &ipv6h->saddr,
+-- 
+2.53.0
+
diff --git a/queue-7.0/hsr-remove-warn_once-in-hsr_addr_is_self.patch b/queue-7.0/hsr-remove-warn_once-in-hsr_addr_is_self.patch
new file mode 100644 (file)
index 0000000..93dcd8a
--- /dev/null
@@ -0,0 +1,109 @@
+From d8a67a0c83b1b152dfb15d59f6fbcceff3f7e9bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 May 2026 06:42:58 +0000
+Subject: hsr: Remove WARN_ONCE() in hsr_addr_is_self().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit afd0f17ca46258cec3a5cc48b8df9327fe772490 ]
+
+syzbot reported the warning [0] in hsr_addr_is_self(),
+whose assumption is simply wrong.
+
+hsr->self_node is cleared in hsr_del_self_node(), which
+is called from hsr_dellink().
+
+Since dev->rtnl_link_ops->dellink() is called before
+unregister_netdevice_many(), there is a window when
+user can find the device but without hsr->self_node.
+
+Let's remove WARN_ONCE() in hsr_addr_is_self().
+
+[0]:
+HSR: No self node
+WARNING: net/hsr/hsr_framereg.c:39 at hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39, CPU#0: syz.4.16848/17220
+Modules linked in:
+CPU: 0 UID: 0 PID: 17220 Comm: syz.4.16848 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:hsr_addr_is_self+0x211/0x3f0 net/hsr/hsr_framereg.c:39
+Code: 33 2f 41 0f b7 dd 89 ee 09 de 31 ff e8 c8 b4 c6 f6 09 dd 74 54 e8 0f b0 c6 f6 31 ed eb 53 e8 06 b0 c6 f6 48 8d 3d 2f 50 9c 04 <67> 48 0f b9 3a 31 ed eb 42 e8 c1 13 1f 00 89 c5 31 ff 89 c6 e8 96
+RSP: 0018:ffffc900041c70e0 EFLAGS: 00010283
+RAX: ffffffff8afdc6ca RBX: ffffffff8afdc4e6 RCX: 0000000000080000
+RDX: ffffc90010493000 RSI: 0000000000000948 RDI: ffffffff8f9a1700
+RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
+R10: ffffc900041c71e8 R11: fffff52000838e3f R12: dffffc0000000000
+R13: ffff888041f9e3c0 R14: ffff888086ee3802 R15: 0000000000000000
+FS:  00007f6fe985d6c0(0000) GS:ffff888126176000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f80bd437dac CR3: 0000000025096000 CR4: 00000000003526f0
+DR0: ffffffffffffffff DR1: 00000000000001f8 DR2: 0000000000000002
+DR3: ffffffffefffff15 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ check_local_dest net/hsr/hsr_forward.c:592 [inline]
+ fill_frame_info net/hsr/hsr_forward.c:728 [inline]
+ hsr_forward_skb+0xa11/0x2a80 net/hsr/hsr_forward.c:739
+ hsr_dev_xmit+0x253/0x370 net/hsr/hsr_device.c:236
+ __netdev_start_xmit include/linux/netdevice.h:5368 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5377 [inline]
+ xmit_one net/core/dev.c:3888 [inline]
+ dev_hard_start_xmit+0x2df/0x860 net/core/dev.c:3904
+ __dev_queue_xmit+0x1428/0x3900 net/core/dev.c:4870
+ neigh_output include/net/neighbour.h:556 [inline]
+ ip_finish_output2+0xcec/0x10b0 net/ipv4/ip_output.c:237
+ ip_send_skb net/ipv4/ip_output.c:1510 [inline]
+ ip_push_pending_frames+0x8b/0x110 net/ipv4/ip_output.c:1530
+ raw_sendmsg+0x1547/0x1a50 net/ipv4/raw.c:659
+ sock_sendmsg_nosec net/socket.c:787 [inline]
+ __sock_sendmsg net/socket.c:802 [inline]
+ ____sys_sendmsg+0x7da/0x9c0 net/socket.c:2698
+ ___sys_sendmsg+0x2a5/0x360 net/socket.c:2752
+ __sys_sendmsg net/socket.c:2784 [inline]
+ __do_sys_sendmsg net/socket.c:2789 [inline]
+ __se_sys_sendmsg net/socket.c:2787 [inline]
+ __x64_sys_sendmsg+0x1c3/0x2a0 net/socket.c:2787
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f6feb62ce59
+Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f6fe985d028 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f6feb8a6090 RCX: 00007f6feb62ce59
+RDX: 0000000000000000 RSI: 0000200000000000 RDI: 0000000000000004
+RBP: 00007f6feb6c2d6f R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007f6feb8a6128 R14: 00007f6feb8a6090 R15: 00007ffcf01cc488
+ </TASK>
+
+Fixes: f266a683a480 ("net/hsr: Better frame dispatch")
+Reported-by: syzbot+652670cf249077eb498b@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1a861e.b111c304.35cd64.0016.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260530064300.340793-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_framereg.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index f268e469af4f09..7f55e12edc8341 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -35,10 +35,8 @@ bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr)
+       rcu_read_lock();
+       sn = rcu_dereference(hsr->self_node);
+-      if (!sn) {
+-              WARN_ONCE(1, "HSR: No self node\n");
++      if (!sn)
+               goto out;
+-      }
+       if (ether_addr_equal(addr, sn->macaddress_A) ||
+           ether_addr_equal(addr, sn->macaddress_B))
+-- 
+2.53.0
+
diff --git a/queue-7.0/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch b/queue-7.0/ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
new file mode 100644 (file)
index 0000000..5ca885c
--- /dev/null
@@ -0,0 +1,56 @@
+From df9cf98bb3209402dc64068b9870ce0487e621d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 07:29:55 +0000
+Subject: ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3a5f3f7aff18bcc36a57839cf50cf0cc8de707f3 ]
+
+The aoe driver (or similar) generates a non-IPv6 packet
+(e.g., ETH_P_AOE) and queues it for transmission via dev_queue_xmit()
+on a 6LoWPAN interface (configured by the user or test case).
+
+Since the packet is not IPv6, the 6LoWPAN header_ops->create function
+(lowpan_header_create or header_create) returns early without initializing
+the lowpan_addr_info structure in the skb headroom.
+
+In the transmit function (lowpan_xmit), the driver calls lowpan_header
+(or setup_header) which unconditionally copies and uses the lowpan_addr_info
+from the headroom, which contains uninitialized data.
+
+Fix this by dropping non IPv6 packets.
+
+A similar fix is needed in net/bluetooth/6lowpan.c bt_xmit().
+
+Fixes: 4dc315e267fe ("ieee802154: 6lowpan: move transmit functionality")
+Reported-by: syzbot+f13c19f75e1097abd116@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6a1fd763.278b5b03.2bcf39.0049.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260603072955.4032221-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ieee802154/6lowpan/tx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
+index 0c07662b44c0ca..4df76ff50699ed 100644
+--- a/net/ieee802154/6lowpan/tx.c
++++ b/net/ieee802154/6lowpan/tx.c
+@@ -255,6 +255,11 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
+       pr_debug("package xmit\n");
++      if (skb->protocol != htons(ETH_P_IPV6)) {
++              kfree_skb(skb);
++              return NET_XMIT_DROP;
++      }
++
+       WARN_ON_ONCE(skb->len > IPV6_MIN_MTU);
+       /* We must take a copy of the skb before we modify/replace the ipv6
+-- 
+2.53.0
+
diff --git a/queue-7.0/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch b/queue-7.0/ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
new file mode 100644 (file)
index 0000000..b8ced33
--- /dev/null
@@ -0,0 +1,54 @@
+From 99777d39a256dd0a5578fe3c4f483a96630295e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 16:15:47 +0000
+Subject: ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d3915a1f5a4bc0ac911032903c3c6ab8df9fcc7c ]
+
+This patch restricts setting Loose Source and Record Route (LSRR)
+and Strict Source and Record Route (SSRR) IP options to users
+with CAP_NET_RAW capability.
+
+This prevents unprivileged applications from forcing packets to route
+through attacker-controlled nodes to leak TCP ISN and possibly other
+protocol information.
+
+While LSRR and SSRR are commonly filtered in many network environments,
+they may still be supported and forwarded along some network paths.
+
+RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing
+IPv4 Options) recommend to drop these options in 4.3 and 4.4.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Tamir Shahar <tamirthesis@gmail.com>
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260602161547.2642155-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_options.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index be8815ce3ac242..09d745112c1526 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -530,6 +530,10 @@ int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+               kfree(opt);
+               return -EINVAL;
+       }
++      if (opt->opt.srr && !ns_capable(net->user_ns, CAP_NET_RAW)) {
++              kfree(opt);
++              return -EPERM;
++      }
+       kfree(*optp);
+       *optp = opt;
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.0/ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch b/queue-7.0/ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch
new file mode 100644 (file)
index 0000000..447d722
--- /dev/null
@@ -0,0 +1,124 @@
+From 65409163671bf0708082f51a9e8e4e0ef5fbf070 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 23:22:18 +0800
+Subject: ipv6: anycast: insert aca into global hash under idev->lock
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit f723ccaff2fb72b71ae8a9fd283f0dee4d9ae7a3 ]
+
+syzbot reported a splat [1]: a slab-use-after-free in
+ipv6_chk_acast_addr(), which walks the global inet6_acaddr_lst[] hash
+under RCU and dereferences a struct ifacaddr6 that has already been
+freed while still linked in the hash, so a later reader walks into a
+dangling node.
+
+In __ipv6_dev_ac_inc() the aca is allocated with refcount 1, then
+aca_get() bumps it to 2 to keep it alive across the unlocked region.
+It is published to idev->ac_list under idev->lock, but
+ipv6_add_acaddr_hash() runs after write_unlock_bh(). A concurrent
+teardown (ipv6_ac_destroy_dev() from addrconf_ifdown(), under RTNL)
+can slip into that window:
+
+  CPU0 __ipv6_dev_ac_inc           CPU1 ipv6_ac_destroy_dev (RTNL)
+  ------------------------------   ------------------------------------
+  aca_alloc()              refcnt 1
+  aca_get()               refcnt 2
+  write_lock_bh(idev->lock)
+    add aca to ac_list
+  write_unlock_bh(idev->lock)
+                                   write_lock_bh(idev->lock)
+                                     pull aca off ac_list
+                                   write_unlock_bh(idev->lock)
+                                   ipv6_del_acaddr_hash(aca)
+                                     hlist_del_init_rcu() is a no-op,
+                                     aca is not in the hash yet
+                                   aca_put()           refcnt 2->1
+  ipv6_add_acaddr_hash(aca)
+    aca now inserted into the hash
+  aca_put()                refcnt 1->0
+    call_rcu(aca_free_rcu) -> kfree(aca)
+
+The hash removal becomes a no-op because the insertion has not
+happened yet, so once CPU0 inserts and drops the last reference, the
+aca is freed while still linked in inet6_acaddr_lst[], and readers
+dereference freed memory after the slab slot is reused.
+
+This window opened once RTNL stopped serializing the join path against
+device teardown. Move ipv6_add_acaddr_hash() inside the idev->lock
+section so the ac_list and hash insertions are atomic with respect to
+teardown: a racing remover now either misses the aca entirely or finds
+it in both lists.
+
+acaddr_hash_lock is now nested under idev->lock, which is acquired in
+softirq context, so switch all acaddr_hash_lock sites to spin_lock_bh()
+to avoid the irq lock inversion reported in [2].
+
+[1] https://syzkaller.appspot.com/bug?extid=a01df04303c131efbf3a
+[2] https://lore.kernel.org/netdev/6a194ef7.ba3b1513.1890b4.0000.GAE@google.com/
+
+Reported-by: syzbot+819eb928d120d2bdad0e@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a191f87.ce022c6e.138e56.0003.GAE@google.com/T/
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Fixes: eb1ac9ff6c4a ("ipv6: anycast: Don't hold RTNL for IPV6_JOIN_ANYCAST.")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260529152219.235475-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/anycast.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
+index 67a42e01dfc3f0..be6dac8a8566a1 100644
+--- a/net/ipv6/anycast.c
++++ b/net/ipv6/anycast.c
+@@ -243,16 +243,16 @@ static void ipv6_add_acaddr_hash(struct net *net, struct ifacaddr6 *aca)
+ {
+       unsigned int hash = inet6_acaddr_hash(net, &aca->aca_addr);
+-      spin_lock(&acaddr_hash_lock);
++      spin_lock_bh(&acaddr_hash_lock);
+       hlist_add_head_rcu(&aca->aca_addr_lst, &inet6_acaddr_lst[hash]);
+-      spin_unlock(&acaddr_hash_lock);
++      spin_unlock_bh(&acaddr_hash_lock);
+ }
+ static void ipv6_del_acaddr_hash(struct ifacaddr6 *aca)
+ {
+-      spin_lock(&acaddr_hash_lock);
++      spin_lock_bh(&acaddr_hash_lock);
+       hlist_del_init_rcu(&aca->aca_addr_lst);
+-      spin_unlock(&acaddr_hash_lock);
++      spin_unlock_bh(&acaddr_hash_lock);
+ }
+ static void aca_get(struct ifacaddr6 *aca)
+@@ -371,10 +371,10 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
+       aca->aca_next = idev->ac_list;
+       rcu_assign_pointer(idev->ac_list, aca);
+-      write_unlock_bh(&idev->lock);
+-
+       ipv6_add_acaddr_hash(net, aca);
++      write_unlock_bh(&idev->lock);
++
+       ip6_ins_rt(net, f6i);
+       addrconf_join_solict(idev->dev, &aca->aca_addr);
+@@ -649,8 +649,8 @@ void ipv6_anycast_cleanup(void)
+ {
+       int i;
+-      spin_lock(&acaddr_hash_lock);
++      spin_lock_bh(&acaddr_hash_lock);
+       for (i = 0; i < IN6_ADDR_HSIZE; i++)
+               WARN_ON(!hlist_empty(&inet6_acaddr_lst[i]));
+-      spin_unlock(&acaddr_hash_lock);
++      spin_unlock_bh(&acaddr_hash_lock);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch b/queue-7.0/ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
new file mode 100644 (file)
index 0000000..c57410b
--- /dev/null
@@ -0,0 +1,107 @@
+From c9d11fe24aba67d9adbd03e528b6adc93bb27b39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 13:18:11 +0300
+Subject: ipv6: mcast: Fix use-after-free when processing MLD queries
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ]
+
+When processing an MLD query, a pointer to the multicast group address
+is retrieved when initially parsing the packet. This pointer is later
+dereferenced without being reloaded despite the fact that the skb header
+might have been reallocated following the pskb_may_pull() calls, leading
+to a use-after-free [1].
+
+Fix by copying the multicast group address when the packet is initially
+parsed.
+
+[1]
+BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512)
+Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
+
+Workqueue: mld mld_query_work
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+print_address_description.constprop.0 (mm/kasan/report.c:378)
+print_report (mm/kasan/report.c:482)
+kasan_report (mm/kasan/report.c:595)
+__mld_query_work (net/ipv6/mcast.c:1512)
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+</TASK>
+
+[...]
+
+Freed by task 118:
+kasan_save_stack (mm/kasan/common.c:57)
+kasan_save_track (mm/kasan/common.c:78)
+kasan_save_free_info (mm/kasan/generic.c:584)
+__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
+kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566)
+pskb_expand_head (net/core/skbuff.c:2335)
+__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4))
+__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
+mld_query_work (net/ipv6/mcast.c:1563)
+process_one_work (kernel/workqueue.c:3314)
+worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478)
+kthread (kernel/kthread.c:436)
+ret_from_fork (arch/x86/kernel/process.c:158)
+ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
+
+Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Reviewed-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/mcast.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index 3330adcf26db24..d9b855d5191bf6 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1424,9 +1424,9 @@ void igmp6_event_query(struct sk_buff *skb)
+ static void __mld_query_work(struct sk_buff *skb)
+ {
+       struct mld2_query *mlh2 = NULL;
+-      const struct in6_addr *group;
+       unsigned long max_delay;
+       struct inet6_dev *idev;
++      struct in6_addr group;
+       struct ifmcaddr6 *ma;
+       struct mld_msg *mld;
+       int group_type;
+@@ -1458,8 +1458,8 @@ static void __mld_query_work(struct sk_buff *skb)
+               goto kfree_skb;
+       mld = (struct mld_msg *)icmp6_hdr(skb);
+-      group = &mld->mld_mca;
+-      group_type = ipv6_addr_type(group);
++      group = mld->mld_mca;
++      group_type = ipv6_addr_type(&group);
+       if (group_type != IPV6_ADDR_ANY &&
+           !(group_type&IPV6_ADDR_MULTICAST))
+@@ -1509,7 +1509,7 @@ static void __mld_query_work(struct sk_buff *skb)
+               }
+       } else {
+               for_each_mc_mclock(idev, ma) {
+-                      if (!ipv6_addr_equal(group, &ma->mca_addr))
++                      if (!ipv6_addr_equal(&group, &ma->mca_addr))
+                               continue;
+                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                               /* gsquery <- gsquery && mark */
+-- 
+2.53.0
+
diff --git a/queue-7.0/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch b/queue-7.0/ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
new file mode 100644 (file)
index 0000000..76a0c61
--- /dev/null
@@ -0,0 +1,127 @@
+From 783e1c75875a65d9e173ee633ad7717facc56d79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 07:07:44 +0300
+Subject: ipvs: clear the svc scheduler ptr early on edit
+
+From: Julian Anastasov <ja@ssi.bg>
+
+[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
+
+ip_vs_edit_service() while unbinding the old scheduler clears
+the svc->scheduler ptr after the scheduler module initiates
+RCU callbacks. This can cause packets to use the old
+scheduler at the time when svc->sched_data is already freed
+after RCU grace period.
+
+Fix it by clearing the ptr early in ip_vs_unbind_scheduler(),
+before the done_service method schedules any RCU callbacks.
+
+Also, if the new scheduler fails to initialize when replacing
+the old scheduler, try to restore the old scheduler while still
+returning the error code.
+
+Link: https://sashiko.dev/#/patchset/20260519015506.634185-1-rosenp%40gmail.com
+Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
+Signed-off-by: Julian Anastasov <ja@ssi.bg>
+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/net/ip_vs.h              |  3 +--
+ net/netfilter/ipvs/ip_vs_ctl.c   | 13 ++++++++-----
+ net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++-------
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 29a36709e7f35c..2163f32ef6abc1 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1519,8 +1519,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+                        struct ip_vs_scheduler *scheduler);
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched);
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+ struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+ struct ip_vs_conn *
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 2aaf50f52c8e8e..ff55ff6b8a4cba 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1496,7 +1496,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
+       if (ret_hooks >= 0)
+               ip_vs_unregister_hooks(ipvs, u->af);
+       if (svc != NULL) {
+-              ip_vs_unbind_scheduler(svc, sched);
++              ip_vs_unbind_scheduler(svc);
+               ip_vs_service_free(svc);
+       }
+       ip_vs_scheduler_put(sched);
+@@ -1558,9 +1558,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+       if (sched != old_sched) {
+               if (old_sched) {
+-                      ip_vs_unbind_scheduler(svc, old_sched);
+-                      RCU_INIT_POINTER(svc->scheduler, NULL);
+-                      /* Wait all svc->sched_data users */
++                      ip_vs_unbind_scheduler(svc);
++                      /* Wait all svc->scheduler/sched_data users */
+                       synchronize_rcu();
+               }
+               /* Bind the new scheduler */
+@@ -1568,6 +1567,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
+                       ret = ip_vs_bind_scheduler(svc, sched);
+                       if (ret) {
+                               ip_vs_scheduler_put(sched);
++                              /* Try to restore the old_sched */
++                              if (old_sched &&
++                                  !ip_vs_bind_scheduler(svc, old_sched))
++                                      old_sched = NULL;
+                               goto out;
+                       }
+               }
+@@ -1624,7 +1627,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
+       /* Unbind scheduler */
+       old_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      ip_vs_unbind_scheduler(svc, old_sched);
++      ip_vs_unbind_scheduler(svc);
+       ip_vs_scheduler_put(old_sched);
+       /* Unbind persistence engine, keep svc->pe */
+diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
+index c6e421c4e29913..24adc38942a0d1 100644
+--- a/net/netfilter/ipvs/ip_vs_sched.c
++++ b/net/netfilter/ipvs/ip_vs_sched.c
+@@ -56,19 +56,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ /*
+  *  Unbind a service with its scheduler
+  */
+-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+-                          struct ip_vs_scheduler *sched)
++void ip_vs_unbind_scheduler(struct ip_vs_service *svc)
+ {
+-      struct ip_vs_scheduler *cur_sched;
++      struct ip_vs_scheduler *sched;
+-      cur_sched = rcu_dereference_protected(svc->scheduler, 1);
+-      /* This check proves that old 'sched' was installed */
+-      if (!cur_sched)
++      sched = rcu_dereference_protected(svc->scheduler, 1);
++      if (!sched)
+               return;
++      /* Reset the scheduler before initiating any RCU callbacks */
++      rcu_assign_pointer(svc->scheduler, NULL);
++      smp_wmb();      /* paired with smp_rmb() in ip_vs_schedule() */
+       if (sched->done_service)
+               sched->done_service(svc);
+-      /* svc->scheduler can be set to NULL only by caller */
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch b/queue-7.0/ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
new file mode 100644 (file)
index 0000000..ab1348f
--- /dev/null
@@ -0,0 +1,75 @@
+From 0676d1aba2298e92d136d853b013c7ecf4db7c39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 00:00:00 +0000
+Subject: ksmbd: fix NULL-deref of opinfo->conn in oplock/lease break notifiers
+
+From: Gil Portnoy <dddhkts1@gmail.com>
+
+[ Upstream commit b003086d76968298f22e7cf62239833b5a3a06b1 ]
+
+smb2_oplock_break_noti() and smb2_lease_break_noti() read opinfo->conn
+into a local with neither READ_ONCE() nor a NULL check.  Both run from
+oplock_break() after opinfo_get_list() has dropped ci->m_lock, so a
+concurrent SMB2 LOGOFF (session_fd_check()) can set op->conn = NULL
+under ci->m_lock within that window.  ksmbd_conn_r_count_inc(conn) then
+writes through NULL at offset 0xc4 -- a remotely triggerable oops.
+
+Guard both reads the way compare_guid_key() already does: read
+opinfo->conn with READ_ONCE() and return early if it is NULL, before
+allocating the work struct so nothing leaks.  A NULL conn means the
+client is gone and the break is moot, so return 0; oplock_break() treats
+that as success and runs the normal teardown.
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Assisted-by: Henry (Claude):claude-opus-4
+Signed-off-by: Gil Portnoy <dddhkts1@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/oplock.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index f5ec1283b16edf..d09fa50ba03a29 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -714,11 +714,16 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
+  */
+ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct oplock_break_info *br_info;
+       int ret = 0;
+-      struct ksmbd_work *work = ksmbd_alloc_work_struct();
++      struct ksmbd_work *work;
++
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++      work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+@@ -818,11 +823,15 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
+  */
+ static int smb2_lease_break_noti(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn = opinfo->conn;
++      struct ksmbd_conn *conn;
+       struct ksmbd_work *work;
+       struct lease_break_info *br_info;
+       struct lease *lease = opinfo->o_lease;
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++
+       work = ksmbd_alloc_work_struct();
+       if (!work)
+               return -ENOMEM;
+-- 
+2.53.0
+
diff --git a/queue-7.0/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch b/queue-7.0/l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch
new file mode 100644 (file)
index 0000000..fb6d026
--- /dev/null
@@ -0,0 +1,176 @@
+From 548129a1d727b694a88b07a6207328064e66a157 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:36:29 +0000
+Subject: l2tp: pppol2tp: hold reference to session in pppol2tp_ioctl()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit a213a8950414c684999dcf03edeea6c46ede172e ]
+
+pppol2tp_ioctl() read sock->sk->sk_user_data directly without any
+locks or reference counting.  If a controllable sleep was induced during
+copy_from_user() (e.g. via a userfaultfd page fault sleep), a concurrent
+socket close could trigger pppol2tp_session_close() asynchronously.  This
+frees the l2tp_session structure via the l2tp_session_del_work workqueue.
+Upon resuming, the ioctl thread dereferences the stale session pointer,
+resulting in a Use-After-Free (UAF).
+
+Fix this by securely fetching the session reference using the RCU-safe,
+refcounted helper pppol2tp_sock_to_session(sk) on entry.  This locks the
+session's refcount across the sleep.  We structured the function to exit
+via standard err breaks, guaranteeing that l2tp_session_put() is cleanly
+called on all return paths to drop the reference.
+
+To preserve existing behavior we validate the session and its magic
+signature only for the specific L2TP commands that require it.  This
+ensures that generic/unknown ioctls called on an unconnected socket
+still return -ENOIOCTLCMD and correctly fall back to generic handlers
+(e.g. in sock_do_ioctl()).
+
+Signed-off-by: Lee Jones <lee@kernel.org>
+Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts")
+Link: https://patch.msgid.link/20260527133630.2120612-1-lee@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_ppp.c | 82 +++++++++++++++++++++++++++------------------
+ 1 file changed, 50 insertions(+), 32 deletions(-)
+
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index ae4543d5597b66..8ff8bf45dc2231 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -1044,64 +1044,76 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+ {
+       struct pppol2tp_ioc_stats stats;
+       struct l2tp_session *session;
++      int err = 0;
++
++      session = pppol2tp_sock_to_session(sock->sk);
++      /* Validate session presence and magic integrity ONLY for commands
++       * that belong to L2TP and require a valid session.
++       */
+       switch (cmd) {
+       case PPPIOCGMRU:
+       case PPPIOCGFLAGS:
+-              session = sock->sk->sk_user_data;
++      case PPPIOCSMRU:
++      case PPPIOCSFLAGS:
++      case PPPIOCGL2TPSTATS:
+               if (!session)
+                       return -ENOTCONN;
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
++              if (session->magic != L2TP_SESSION_MAGIC) {
++                      l2tp_session_put(session);
+                       return -EBADF;
++              }
++              break;
++      default:
++              break;
++      }
++      switch (cmd) {
++      case PPPIOCGMRU:
++      case PPPIOCGFLAGS:
+               /* Not defined for tunnels */
+-              if (!session->session_id && !session->peer_session_id)
+-                      return -ENOSYS;
++              if (!session->session_id && !session->peer_session_id) {
++                      err = -ENOSYS;
++                      break;
++              }
+-              if (put_user(0, (int __user *)arg))
+-                      return -EFAULT;
++              if (put_user(0, (int __user *)arg)) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       case PPPIOCSMRU:
+       case PPPIOCSFLAGS:
+-              session = sock->sk->sk_user_data;
+-              if (!session)
+-                      return -ENOTCONN;
+-
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
+-                      return -EBADF;
+-
+               /* Not defined for tunnels */
+-              if (!session->session_id && !session->peer_session_id)
+-                      return -ENOSYS;
++              if (!session->session_id && !session->peer_session_id) {
++                      err = -ENOSYS;
++                      break;
++              }
+-              if (!access_ok((int __user *)arg, sizeof(int)))
+-                      return -EFAULT;
++              if (!access_ok((int __user *)arg, sizeof(int))) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       case PPPIOCGL2TPSTATS:
+-              session = sock->sk->sk_user_data;
+-              if (!session)
+-                      return -ENOTCONN;
+-
+-              if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
+-                      return -EBADF;
+-
+               /* Session 0 represents the parent tunnel */
+               if (!session->session_id && !session->peer_session_id) {
+                       u32 session_id;
+-                      int err;
+                       if (copy_from_user(&stats, (void __user *)arg,
+-                                         sizeof(stats)))
+-                              return -EFAULT;
++                                         sizeof(stats))) {
++                              err = -EFAULT;
++                              break;
++                      }
+                       session_id = stats.session_id;
+                       err = pppol2tp_tunnel_copy_stats(&stats,
+                                                        session->tunnel);
+                       if (err < 0)
+-                              return err;
++                              break;
+                       stats.session_id = session_id;
+               } else {
+@@ -1111,15 +1123,21 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+               stats.tunnel_id = session->tunnel->tunnel_id;
+               stats.using_ipsec = l2tp_tunnel_uses_xfrm(session->tunnel);
+-              if (copy_to_user((void __user *)arg, &stats, sizeof(stats)))
+-                      return -EFAULT;
++              if (copy_to_user((void __user *)arg, &stats, sizeof(stats))) {
++                      err = -EFAULT;
++                      break;
++              }
+               break;
+       default:
+-              return -ENOIOCTLCMD;
++              err = -ENOIOCTLCMD;
++              break;
+       }
+-      return 0;
++      if (session)
++              l2tp_session_put(session);
++
++      return err;
+ }
+ /*****************************************************************************
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch b/queue-7.0/net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
new file mode 100644 (file)
index 0000000..5863d00
--- /dev/null
@@ -0,0 +1,79 @@
+From b744e60c9be3a652d01a727ffbe0505f8555199a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:00:13 +0800
+Subject: net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 7561c7fbc694308da73300f036719e63e42bf0b4 ]
+
+In mrp_pdu_parse_vecattr(), vector attribute events are encoded three
+per byte and valen tracks the number of events left to process.
+
+The parser decrements valen after processing the first and second events
+from each event byte, but not after processing the third one. When valen
+is exactly a multiple of three, the loop continues after the last valid
+event and consumes the next byte as a new event byte, applying a
+spurious event to the MRP applicant state.
+
+Additionally, when valen is zero the parser unconditionally consumes
+attrlen bytes as FirstValue and advances the offset, even though per
+IEEE 802.1ak a VectorAttribute with only a LeaveAllEvent has valen of
+zero and no FirstValue or Vector fields. This corrupts the offset for
+subsequent PDU parsing.
+
+Also, when valen exceeds three the loop crosses byte boundaries but
+the attribute value is not incremented between the last event of one
+byte and the first event of the next. This causes the first event of
+the next byte to use the same attribute value as the third event
+rather than the next consecutive value.
+
+Decrement valen after processing the third event, skip FirstValue
+consumption when valen is zero, and increment the attribute value at
+the end of each loop iteration.
+
+Fixes: febf018d2234 ("net/802: Implement Multiple Registration Protocol (MRP)")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Link: https://patch.msgid.link/20260603060016.21522-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/mrp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index ff0e80574e6b7b..160a3b14569cbd 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -703,6 +703,12 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+       valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
+                           MRP_VECATTR_HDR_LEN_MASK);
++      /* If valen is 0, only a LeaveAllEvent is present; FirstValue and
++       * Vector fields are absent per IEEE 802.1ak.
++       */
++      if (valen == 0)
++              return 0;
++
+       /* The VectorAttribute structure in a PDU carries event information
+        * about one or more attributes having consecutive values. Only the
+        * value for the first attribute is contained in the structure. So
+@@ -753,6 +759,9 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
+               vaevents %= __MRP_VECATTR_EVENT_MAX;
+               vaevent = vaevents;
+               mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++              valen--;
++              mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++                                mrp_cb(skb)->mh->attrlen);
+       }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch b/queue-7.0/net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch
new file mode 100644 (file)
index 0000000..145d1e3
--- /dev/null
@@ -0,0 +1,47 @@
+From 07e6ea0a9cb66f770fba098955b0a2f43a00a166 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:21:04 +0200
+Subject: net: airoha: Fix use-after-free in metadata dst teardown
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit b38cae85d1c45ff189d7ecb6ac36f41cdc3d84d0 ]
+
+airoha_metadata_dst_free() runs metadata_dst_free() which frees the
+metadata_dst with kfree() immediately, bypassing the RCU grace period.
+In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
+the skb to the metadata_dst. This function requires RCU read-side
+protection and the dst must remain valid until all RCU readers complete.
+Since metadata_dst_free() calls kfree() directly, an use-after-free can
+occur if any skb still holds a noref pointer to the dst when the driver
+tears it down.
+Replace metadata_dst_free() with dst_release() which properly goes
+through the refcount path: when the refcount drops to zero, it schedules
+the actual free via call_rcu_hurry(), ensuring all RCU readers have
+completed before the memory is freed.
+
+Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-1-3aaa99d83351@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
+index 13f74335928660..698a305ca694c6 100644
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -2935,7 +2935,7 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
+               if (!port->dsa_meta[i])
+                       continue;
+-              metadata_dst_free(port->dsa_meta[i]);
++              dst_release(&port->dsa_meta[i]->dst);
+       }
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-annotate-sk-sk_write_space-for-udp-sockmap.patch b/queue-7.0/net-annotate-sk-sk_write_space-for-udp-sockmap.patch
new file mode 100644 (file)
index 0000000..442e14b
--- /dev/null
@@ -0,0 +1,60 @@
+From 3d941cedd822da23ef6bf06fc68f43591772ee04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:39:23 +0000
+Subject: net: Annotate sk->sk_write_space() for UDP SOCKMAP.
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit b748765019fe9e9234660327090fc1a9665cdbdd ]
+
+UDP TX skb->destructor() is sock_wfree(), and UDP holds lock_sock()
+only for UDP_CORK / MSG_MORE sendmsg().
+
+Otherwise, sk->sk_write_space() may be read locklessly while SOCKMAP
+rewrites sk->sk_write_space().
+
+Let's use WRITE_ONCE() and READ_ONCE() for sk->sk_write_space().
+
+Note that the write side is annotated by commit 2ef2b20cf4e0
+("net: annotate data-races around sk->sk_{data_ready,write_space}").
+
+Fixes: 7b98cd42b049 ("bpf: sockmap: Add UDP support")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://patch.msgid.link/20260529193941.3897256-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 5976100a9d55a0..b197a795306392 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2673,8 +2673,12 @@ void sock_wfree(struct sk_buff *skb)
+       int old;
+       if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
++              void (*sk_write_space)(struct sock *sk);
++
++              sk_write_space = READ_ONCE(sk->sk_write_space);
++
+               if (sock_flag(sk, SOCK_RCU_FREE) &&
+-                  sk->sk_write_space == sock_def_write_space) {
++                  sk_write_space == sock_def_write_space) {
+                       rcu_read_lock();
+                       free = __refcount_sub_and_test(len, &sk->sk_wmem_alloc,
+                                                      &old);
+@@ -2690,7 +2694,7 @@ void sock_wfree(struct sk_buff *skb)
+                * after sk_write_space() call
+                */
+               WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
+-              sk->sk_write_space(sk);
++              sk_write_space(sk);
+               len = 1;
+       }
+       /*
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch b/queue-7.0/net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
new file mode 100644 (file)
index 0000000..f333cff
--- /dev/null
@@ -0,0 +1,48 @@
+From e7086575ae3f8882dfe972b02a2bf17a81386ebf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:21:05 +0200
+Subject: net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst
+ teardown
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit 80df409e1a483676826a6c66e693dba6ac507751 ]
+
+mtk_free_dev() calls metadata_dst_free() which frees the metadata_dst
+with kfree() immediately, bypassing the RCU grace period.
+In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from
+the skb to the metadata_dst. This function requires RCU read-side
+protection and the dst must remain valid until all RCU readers complete.
+Since metadata_dst_free() calls kfree() directly, a use-after-free can
+occur if any skb still holds a noref pointer to the dst when the driver
+tears it down.
+Replace metadata_dst_free() with dst_release() which properly goes
+through the refcount path: when the refcount drops to zero, it schedules
+the actual free via call_rcu_hurry(), ensuring all RCU readers have
+completed before the memory is freed.
+
+Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-2-3aaa99d83351@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index 796f79088f3662..2eca2b2a964fef 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -4469,7 +4469,7 @@ static int mtk_free_dev(struct mtk_eth *eth)
+       for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
+               if (!eth->dsa_meta[i])
+                       break;
+-              metadata_dst_free(eth->dsa_meta[i]);
++              dst_release(&eth->dsa_meta[i]->dst);
+       }
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch b/queue-7.0/net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
new file mode 100644 (file)
index 0000000..7fa8256
--- /dev/null
@@ -0,0 +1,62 @@
+From c6ccbb159511bbfb862fa8c4fb0a83ec8b6ba2cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 06:18:57 +0000
+Subject: net: fec: fix pinctrl default state restore order on resume
+
+From: Tapio Reijonen <tapio.reijonen@vaisala.com>
+
+[ Upstream commit b455410146bf723c7ebcb49ecd5becc0d6611482 ]
+
+In fec_resume(), fec_enet_clk_enable() is called before
+pinctrl_pm_select_default_state() in the non-WoL path, inverting the
+ordering used in fec_suspend() which correctly switches to the sleep
+pinctrl state before disabling clocks.
+
+For PHYs with the PHY_RST_AFTER_CLK_EN flag (e.g. TI DP83848 or
+SMSC LAN87xx), fec_enet_clk_enable() triggers a hardware reset pulse
+via the phy-reset GPIO. With the GPIO pin still in sleep pinctrl state
+at that point, the GPIO write has no physical effect and the PHY never
+receives the required reset after clock enable, leading to unreliable
+link establishment after system resume.
+
+Fix by restoring the default pinctrl state before enabling clocks,
+making resume the proper mirror of suspend. The call is made
+unconditionally: fec_suspend() only switches to the sleep pinctrl state
+on the non-WoL path and leaves the pins in the default state when WoL
+is enabled, so on a WoL resume the device is already in the default
+state and pinctrl_pm_select_default_state() is a no-op.
+
+Fixes: de40ed31b3c5 ("net: fec: add Wake-on-LAN support")
+Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20260529-b4-fec-resume-pinctrl-order-v3-1-6eda0f592fca@vaisala.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index f89aa94ce0202d..6ebde65d7f1b87 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -5594,6 +5594,7 @@ static int fec_resume(struct device *dev)
+               if (fep->rpm_active)
+                       pm_runtime_force_resume(dev);
++              pinctrl_pm_select_default_state(&fep->pdev->dev);
+               ret = fec_enet_clk_enable(ndev, true);
+               if (ret) {
+                       rtnl_unlock();
+@@ -5610,8 +5611,6 @@ static int fec_resume(struct device *dev)
+                       val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
+                       writel(val, fep->hwp + FEC_ECNTRL);
+                       fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
+-              } else {
+-                      pinctrl_pm_select_default_state(&fep->pdev->dev);
+               }
+               fec_restart(ndev);
+               netif_tx_lock_bh(ndev);
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch b/queue-7.0/net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
new file mode 100644 (file)
index 0000000..535a619
--- /dev/null
@@ -0,0 +1,58 @@
+From 4ea1ecbf654227622e401a3e1e3c36a4e45415dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:31:58 +0800
+Subject: net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+[ Upstream commit 16e408e607a94b646fb14a2a98422c6877ae4b3c ]
+
+The receive-side GARP attribute parser computes dlen with reversed
+operands:
+
+        dlen = sizeof(*ga) - ga->len;
+
+ga->len is the on-wire attribute length and includes the GARP attribute
+header. For normal attributes with data, ga->len is larger than
+sizeof(*ga), so the subtraction underflows in unsigned arithmetic.
+
+The resulting value is later passed to garp_attr_lookup(), whose length
+argument is u8. After truncation, the parsed data length usually no
+longer matches the length stored for locally registered attributes, so
+received Join/Leave events are ignored. This breaks the GARP receive path
+for common attributes, such as GVRP VLAN registration attributes.
+
+Compute the data length as the attribute length minus the header length.
+
+Fixes: eca9ebac651f ("net: Add GARP applicant-only participant")
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260527083200.42861-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/802/garp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index 6f563b6797d99e..c7a39f298ad6ed 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -453,7 +453,7 @@ static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
+       if (!pskb_may_pull(skb, ga->len))
+               return -1;
+       skb_pull(skb, ga->len);
+-      dlen = sizeof(*ga) - ga->len;
++      dlen = ga->len - sizeof(*ga);
+       if (attrtype > app->app->maxattr)
+               return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch b/queue-7.0/net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
new file mode 100644 (file)
index 0000000..ab49a89
--- /dev/null
@@ -0,0 +1,99 @@
+From 3f23e96e5d43f3ed96773fa97126a3230c5ded00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:03:00 +0000
+Subject: net: lan743x: permit VLAN-tagged packets up to configured MTU
+
+From: David Thompson <davthompson@nvidia.com>
+
+[ Upstream commit 8173d22b211f615015f7b35f48ab11a6dd78dc99 ]
+
+VLAN-tagged interfaces on lan743x devices were previously unreachable via
+SSH and failed to respond to large ping packets (e.g. "ping -s 1469" given
+MTU=1500). In these scenarios, "ethtool -S" reports non-zero "RX Oversize
+Frame Errors". According to Microchip AN2948, the MAC_RX FSE (VLAN field
+size enforcement) bit determines whether frames with VLAN tags exceeding
+the base MTU plus tag length are discarded.
+
+The driver must set the MAC_RX.FSE bit before setting MAC_RX.RXEN to allow
+VLAN-tagged frames up to the interface MTU, preventing them from being
+treated as oversized. As a result, both the base and VLAN-tagged interfaces
+can use the same MTU without receive errors.
+
+Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver")
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Reviewed-by: Thangaraj Samynathan <Thangaraj.s@microchip.com>
+Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
+Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # lan7430 on arm64 (RevPi
+Link: https://patch.msgid.link/20260529210300.433135-1-davthompson@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h |  1 +
+ 2 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index f0b5dd752f084f..5af49b2b20245d 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -1212,6 +1212,36 @@ static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
+                  "MAC address set to %pM\n", addr);
+ }
++static void lan743x_mac_rx_enable_fse(struct lan743x_adapter *adapter)
++{
++      u32 mac_rx;
++      bool rxen;
++
++      mac_rx = lan743x_csr_read(adapter, MAC_RX);
++      if (mac_rx & MAC_RX_FSE_)
++              return;
++
++      rxen = mac_rx & MAC_RX_RXEN_;
++      if (rxen) {
++              mac_rx &= ~MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++              lan743x_csr_wait_for_bit(adapter, MAC_RX, MAC_RX_RXD_,
++                                       1, 1000, 20000, 100);
++      }
++
++      /* Per AN2948, hardware prevents modification of the FSE bit while the
++       * MAC receiver is enabled (RXEN bit set). Use separate register write
++       * to assert the FSE bit before enabling the RXEN bit in MAC_RX
++       */
++      mac_rx |= MAC_RX_FSE_;
++      lan743x_csr_write(adapter, MAC_RX, mac_rx);
++
++      if (rxen) {
++              mac_rx |= MAC_RX_RXEN_;
++              lan743x_csr_write(adapter, MAC_RX, mac_rx);
++      }
++}
++
+ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+ {
+       bool mac_address_valid = true;
+@@ -1251,6 +1281,8 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
+       lan743x_mac_set_address(adapter, adapter->mac_address);
+       eth_hw_addr_set(netdev, adapter->mac_address);
++      lan743x_mac_rx_enable_fse(adapter);
++
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 02a28b7091630d..b977256b742061 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -181,6 +181,7 @@
+ #define MAC_RX                                (0x104)
+ #define MAC_RX_MAX_SIZE_SHIFT_                (16)
+ #define MAC_RX_MAX_SIZE_MASK_         (0x3FFF0000)
++#define MAC_RX_FSE_                   BIT(2)
+ #define MAC_RX_RXD_                   BIT(1)
+ #define MAC_RX_RXEN_                  BIT(0)
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch b/queue-7.0/net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
new file mode 100644 (file)
index 0000000..c83a78d
--- /dev/null
@@ -0,0 +1,106 @@
+From 168436efcc100637ae89239206f2163c68f81ed0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 12:08:12 -0400
+Subject: net/sched: act_api: use RCU with deferred freeing for action
+ lifecycle
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ]
+
+When NEWTFILTER and DELFILTER are run concurrently it is possible to create a
+race with an associated action.
+
+Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER:
+
+ 0: mutex_lock() <-- holds the idr lock
+ 0: rcu_read_lock()
+ 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR)
+ 0: mutex_unlock() <-- releases the idr lock
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index) <-- Action removed from IDR
+ 1: mutex_unlock() <-- mutex released allowing us to delete the action
+ 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory
+
+This patch fixes the race condition between NEWTFILTER and DELFILTER by
+adding struct rcu_head to tc_action used in the deferral and introducing a
+call_rcu() in the delete path to defer the final kfree().
+
+Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+but also modernization/simplification to directly use kfree_rcu().
+
+Let's illustrate the new restored code path:
+
+ 0: rcu_read_lock()
+ 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held
+ 1: idr_remove(idr, index)
+ 1: mutex_unlock()
+ 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period
+ 0: p = idr_find(idr, index)
+ 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0
+ 1: rcu_read_unlock() <-- release so freeing can run after grace period
+
+After CPU1 calls idr_remove(), the object is no longer reachable through the IDR.
+CPU0's subsequent idr_find() will return NULL, and even if it still held a
+stale pointer, the immediate kfree() is now deferred until after the RCU grace
+period, so no UAF can occur.
+
+Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu")
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Reported-by: Kyle Zeng <kylebot@openai.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: syzbot@syzkaller.appspotmail.com
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Tested-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/act_api.h | 1 +
+ net/sched/act_api.c   | 7 +------
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/act_api.h b/include/net/act_api.h
+index d11b791079302f..fd2967ee08f7a6 100644
+--- a/include/net/act_api.h
++++ b/include/net/act_api.h
+@@ -45,6 +45,7 @@ struct tc_action {
+       struct tc_cookie        __rcu *user_cookie;
+       struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
++      struct rcu_head         tcfa_rcu;
+       u8                      hw_stats;
+       u8                      used_hw_stats;
+       bool                    used_hw_stats_valid;
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index 332fd9695e54a1..04ea11c90e0330 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -112,11 +112,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
+ }
+ EXPORT_SYMBOL(tcf_action_set_ctrlact);
+-/* XXX: For standalone actions, we don't need a RCU grace period either, because
+- * actions are always connected to filters and filters are already destroyed in
+- * RCU callbacks, so after a RCU grace period actions are already disconnected
+- * from filters. Readers later can not find us.
+- */
+ static void free_tcf(struct tc_action *p)
+ {
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
+@@ -129,7 +124,7 @@ static void free_tcf(struct tc_action *p)
+       if (chain)
+               tcf_chain_put_by_act(chain);
+-      kfree(p);
++      kfree_rcu(p, tcfa_rcu);
+ }
+ static void offload_action_hw_count_set(struct tc_action *act,
+-- 
+2.53.0
+
diff --git a/queue-7.0/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch b/queue-7.0/net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
new file mode 100644 (file)
index 0000000..f963074
--- /dev/null
@@ -0,0 +1,228 @@
+From 55fb75027cc77e69164865152a97768230b87766 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 08:32:21 -0400
+Subject: net/sched: fix pedit partial COW leading to page cache corruption
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
+
+[ Upstream commit 899ee91156e57784090c5565e4f31bd7dbffbc5a ]
+
+tcf_pedit_act() computes the COW range for skb_ensure_writable()
+once before the key loop using tcfp_off_max_hint, but the hint does
+not account for the runtime header offset added by typed keys. This
+can leave part of the write region un-COW'd.
+
+Fix by moving skb_ensure_writable() inside the per-key loop where
+the actual write offset is known, and add overflow checking on the
+offset arithmetic. For negative offsets (e.g. Ethernet header edits
+at ingress), use skb_cow() to COW the headroom instead. Guard
+offset_valid() against INT_MIN, where negation is undefined.
+
+Fixes: 8b796475fd78 ("net/sched: act_pedit: really ensure the skb is writable")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Reported-by: Keenan Dong <keenanat2000@gmail.com>
+Reported-by: Han Guidong <2045gemini@gmail.com>
+Reported-by: Zhang Cen <rollkingzzc@gmail.com>
+Reviewed-by: Han Guidong <2045gemini@gmail.com>
+Tested-by: Han Guidong <2045gemini@gmail.com>
+Reviewed-by: Davide Caratti <dcaratti@redhat.com>
+Tested-by: Davide Caratti <dcaratti@redhat.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Tested-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Reviewed-by: Victor Nogueira <victor@mojatatu.com>
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260531123221.48732-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tc_act/tc_pedit.h |  1 -
+ net/sched/act_pedit.c         | 77 +++++++++++++++++++----------------
+ 2 files changed, 41 insertions(+), 37 deletions(-)
+
+diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
+index f58ee15cd858cf..cb7b82f2cbc7fd 100644
+--- a/include/net/tc_act/tc_pedit.h
++++ b/include/net/tc_act/tc_pedit.h
+@@ -15,7 +15,6 @@ struct tcf_pedit_parms {
+       struct tc_pedit_key     *tcfp_keys;
+       struct tcf_pedit_key_ex *tcfp_keys_ex;
+       int action;
+-      u32 tcfp_off_max_hint;
+       unsigned char tcfp_nkeys;
+       unsigned char tcfp_flags;
+       struct rcu_head rcu;
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index bc20f08a278901..bd3b1da3cd63b5 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -16,6 +16,8 @@
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+ #include <linux/slab.h>
++#include <linux/overflow.h>
++#include <linux/unaligned.h>
+ #include <net/ipv6.h>
+ #include <net/netlink.h>
+ #include <net/pkt_sched.h>
+@@ -242,7 +244,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+               goto out_free_ex;
+       }
+-      nparms->tcfp_off_max_hint = 0;
+       nparms->tcfp_flags = parm->flags;
+       nparms->tcfp_nkeys = parm->nkeys;
+@@ -268,14 +269,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+                                                  BITS_PER_TYPE(int) - 1,
+                                                  nparms->tcfp_keys[i].shift);
+-              /* The AT option can read a single byte, we can bound the actual
+-               * value with uchar max.
+-               */
+-              cur += (0xff & offmask) >> nparms->tcfp_keys[i].shift;
+-
+-              /* Each key touches 4 bytes starting from the computed offset */
+-              nparms->tcfp_off_max_hint =
+-                      max(nparms->tcfp_off_max_hint, cur + 4);
+       }
+       p = to_pedit(*a);
+@@ -318,15 +311,12 @@ static void tcf_pedit_cleanup(struct tc_action *a)
+               call_rcu(&parms->rcu, tcf_pedit_cleanup_rcu);
+ }
+-static bool offset_valid(struct sk_buff *skb, int offset)
++static bool offset_valid(struct sk_buff *skb, int offset, int len)
+ {
+-      if (offset > 0 && offset > skb->len)
+-              return false;
+-
+-      if  (offset < 0 && -offset > skb_headroom(skb))
++      if (offset < -(int)skb_headroom(skb))
+               return false;
+-      return true;
++      return offset <= (int)skb->len - len;
+ }
+ static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int header_type)
+@@ -393,18 +383,10 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+       struct tcf_pedit_key_ex *tkey_ex;
+       struct tcf_pedit_parms *parms;
+       struct tc_pedit_key *tkey;
+-      u32 max_offset;
+       int i;
+       parms = rcu_dereference_bh(p->parms);
+-      max_offset = (skb_transport_header_was_set(skb) ?
+-                    skb_transport_offset(skb) :
+-                    skb_network_offset(skb)) +
+-                   parms->tcfp_off_max_hint;
+-      if (skb_ensure_writable(skb, min(skb->len, max_offset)))
+-              goto done;
+-
+       tcf_lastuse_update(&p->tcf_tm);
+       tcf_action_update_bstats(&p->common, skb);
+@@ -412,10 +394,11 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+       tkey_ex = parms->tcfp_keys_ex;
+       for (i = parms->tcfp_nkeys; i > 0; i--, tkey++) {
++              int write_offset, write_len;
+               int offset = tkey->off;
+               int hoffset = 0;
+-              u32 *ptr, hdata;
+-              u32 val;
++              u32 cur_val, val;
++              u32 *ptr;
+               int rc;
+               if (tkey_ex) {
+@@ -433,13 +416,15 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+               if (tkey->offmask) {
+                       u8 *d, _d;
++                      int at_offset;
+-                      if (!offset_valid(skb, hoffset + tkey->at)) {
++                      if (check_add_overflow(hoffset, (int)tkey->at, &at_offset) ||
++                          !offset_valid(skb, at_offset, sizeof(_d))) {
+                               pr_info_ratelimited("tc action pedit 'at' offset %d out of bounds\n",
+                                                   hoffset + tkey->at);
+                               goto bad;
+                       }
+-                      d = skb_header_pointer(skb, hoffset + tkey->at,
++                      d = skb_header_pointer(skb, at_offset,
+                                              sizeof(_d), &_d);
+                       if (!d)
+                               goto bad;
+@@ -451,31 +436,51 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
+                       }
+               }
+-              if (!offset_valid(skb, hoffset + offset)) {
+-                      pr_info_ratelimited("tc action pedit offset %d out of bounds\n", hoffset + offset);
++              if (check_add_overflow(hoffset, offset, &write_offset)) {
++                      pr_info_ratelimited("tc action pedit offset overflow\n");
+                       goto bad;
+               }
+-              ptr = skb_header_pointer(skb, hoffset + offset,
+-                                       sizeof(hdata), &hdata);
+-              if (!ptr)
++              if (!offset_valid(skb, write_offset, sizeof(*ptr))) {
++                      pr_info_ratelimited("tc action pedit offset %d out of bounds\n",
++                                          write_offset);
+                       goto bad;
++              }
++
++              if (write_offset < 0) {
++                      if (skb_cow(skb, -write_offset))
++                              goto bad;
++                      if (write_offset + (int)sizeof(*ptr) > 0) {
++                              if (skb_ensure_writable(skb,
++                                                      min_t(int, skb->len,
++                                                            write_offset + (int)sizeof(*ptr))))
++                                      goto bad;
++                      }
++              } else {
++                      if (check_add_overflow(write_offset, (int)sizeof(*ptr),
++                                             &write_len))
++                              goto bad;
++                      if (skb_ensure_writable(skb, min_t(int, skb->len,
++                                                         write_len)))
++                              goto bad;
++              }
++
++              ptr = (u32 *)(skb->data + write_offset);
++              cur_val = get_unaligned(ptr);
+               /* just do it, baby */
+               switch (cmd) {
+               case TCA_PEDIT_KEY_EX_CMD_SET:
+                       val = tkey->val;
+                       break;
+               case TCA_PEDIT_KEY_EX_CMD_ADD:
+-                      val = (*ptr + tkey->val) & ~tkey->mask;
++                      val = (cur_val + tkey->val) & ~tkey->mask;
+                       break;
+               default:
+                       pr_info_ratelimited("tc action pedit bad command (%d)\n", cmd);
+                       goto bad;
+               }
+-              *ptr = ((*ptr & tkey->mask) ^ val);
+-              if (ptr == &hdata)
+-                      skb_store_bits(skb, hoffset + offset, ptr, 4);
++              put_unaligned((cur_val & tkey->mask) ^ val, ptr);
+       }
+       goto done;
+-- 
+2.53.0
+
diff --git a/queue-7.0/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch b/queue-7.0/netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
new file mode 100644 (file)
index 0000000..83b2719
--- /dev/null
@@ -0,0 +1,58 @@
+From d38a6ce8cbc3bfc14ba87afe3cceb9c5ccc6580f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 12:29:10 +0000
+Subject: netfilter: bridge: make ebt_snat ARP rewrite writable
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 67ba971ae02514d85818fe0c32549ab4bfa3bf49 ]
+
+The ebtables SNAT target keeps the Ethernet source address rewrite
+behind skb_ensure_writable(skb, 0).  This is intentional: at the bridge
+ebtables hooks the Ethernet header is addressed through
+skb_mac_header()/eth_hdr(), while skb->data points at the Ethernet
+payload.  Asking skb_ensure_writable() for ETH_HLEN bytes would check
+the payload, not the Ethernet header, and would reintroduce the small
+packet regression fixed by commit 63137bc5882a.
+
+However, the optional ARP sender hardware address rewrite is different.
+It writes through skb_store_bits() at an offset relative to skb->data:
+
+        skb_store_bits(skb, sizeof(struct arphdr), info->mac, ETH_ALEN)
+
+skb_header_pointer() only safely reads the ARP header; it does not make
+the later sender hardware address range writable.  If that range is
+still held in a nonlinear skb fragment backed by a splice-imported file
+page, skb_store_bits() maps the frag page and copies the new MAC address
+directly into it.
+
+Ensure the ARP SHA range is writable before reading the ARP header and
+before calling skb_store_bits().
+
+Fixes: 63137bc5882a ("netfilter: ebtables: Fixes dropping of small packets in bridge nat")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+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>
+---
+ net/bridge/netfilter/ebt_snat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
+index 7dfbcdfc30e5d2..c9e229af0366b8 100644
+--- a/net/bridge/netfilter/ebt_snat.c
++++ b/net/bridge/netfilter/ebt_snat.c
+@@ -31,6 +31,9 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
+               const struct arphdr *ap;
+               struct arphdr _ah;
++              if (skb_ensure_writable(skb, sizeof(_ah) + ETH_ALEN))
++                      return EBT_DROP;
++
+               ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+               if (ap == NULL)
+                       return EBT_DROP;
+-- 
+2.53.0
+
diff --git a/queue-7.0/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch b/queue-7.0/netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
new file mode 100644 (file)
index 0000000..307dba1
--- /dev/null
@@ -0,0 +1,50 @@
+From d54aa43a229b3216ccc86b479b9719f262529bf9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:20:19 +0200
+Subject: netfilter: conntrack_irc: fix possible out-of-bounds read
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 66eba0ffce3b7e11449946b4cbbef8ea36112f56 ]
+
+When parsing fails after we've matched the command string we
+should bail out instead of trying to match a different command.
+
+This helper should be deprecated, given prevalence of TLS I doubt it has
+any relevance in 2026.
+
+Fixes: 869f37d8e48f ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
+Closes: https://sashiko.dev/#/patchset/20260525182924.28456-1-fw%40strlen.de
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_irc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index b8e6d724acd155..064df01953ebf7 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -209,7 +209,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                       if (parse_dcc(data, data_limit, &dcc_ip,
+                                      &dcc_port, &addr_beg_p, &addr_end_p)) {
+                               pr_debug("unable to parse dcc command\n");
+-                              continue;
++                              goto out;
+                       }
+                       pr_debug("DCC bound ip/port: %pI4:%u\n",
+@@ -223,7 +223,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+                               net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
+                                                    &tuple->src.u3.ip,
+                                                    &dcc_ip, dcc_port);
+-                              continue;
++                              goto out;
+                       }
+                       exp = nf_ct_expect_alloc(ct);
+-- 
+2.53.0
+
diff --git a/queue-7.0/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch b/queue-7.0/netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
new file mode 100644 (file)
index 0000000..97b4934
--- /dev/null
@@ -0,0 +1,96 @@
+From c3155e1c22b49028e5b70fb650becf751a9352f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:09:19 +0800
+Subject: netfilter: nft_ct: bail out on template ct in get eval
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 3027ecbdb5fdf9200251c21d4818e4c447ef78e1 ]
+
+I noticed this issue while looking at a historic syzbot report [1].
+
+A rule like the one below is enough to trigger the bug:
+
+    table ip t {
+        chain pre {
+            type filter hook prerouting priority raw;
+            ct zone set 1
+            ct original saddr 1.2.3.4 accept
+        }
+    }
+
+The first expression attaches a per-cpu template ct via
+nft_ct_set_zone_eval() (nf_ct_tmpl_alloc -> kzalloc, tuple is all
+zero, nf_ct_l3num(ct) == 0). The next expression then calls
+nft_ct_get_eval() on the same skb, treats the template as a real ct
+and hits the 16-byte memcpy path. With dreg at NFT_REG32_15 this
+overflows past struct nft_regs on the kernel stack; with smaller
+dreg values it silently clobbers adjacent registers.
+
+Reject template ct at the eval entry and in nft_ct_get_fast_eval(),
+mirroring the check nft_ct_set_eval() already has. Additionally,
+bound the address copy in NFT_CT_SRC / NFT_CT_DST by priv->len
+instead of by nf_ct_l3num(ct): nf_ct_get_tuple() zeroes the tuple
+before pkt_to_tuple() fills in only the protocol-relevant leading
+bytes, so the trailing bytes of tuple->{src,dst}.u3.all are
+well-defined zero. priv->len is validated at rule load, so the
+copy size is now bounded by the destination register rather than
+by an untrusted field on the conntrack.
+
+[1]: https://syzkaller.appspot.com/bug?id=389cf09cb72926114fce90dc85a2c3231dcb647c
+
+Fixes: 45d9bcda21f4 ("netfilter: nf_tables: validate len in nft_validate_data_load()")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+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>
+---
+ net/netfilter/nft_ct.c      | 8 +++-----
+ net/netfilter/nft_ct_fast.c | 2 +-
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 272ce181180777..92b673f4582a2d 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -78,7 +78,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (ct == NULL)
++      if (!ct || nf_ct_is_template(ct))
+               goto err;
+       switch (priv->key) {
+@@ -180,12 +180,10 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
+       tuple = &ct->tuplehash[priv->dir].tuple;
+       switch (priv->key) {
+       case NFT_CT_SRC:
+-              memcpy(dest, tuple->src.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->src.u3.all, priv->len);
+               return;
+       case NFT_CT_DST:
+-              memcpy(dest, tuple->dst.u3.all,
+-                     nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
++              memcpy(dest, tuple->dst.u3.all, priv->len);
+               return;
+       case NFT_CT_PROTO_SRC:
+               nft_reg_store16(dest, (__force u16)tuple->src.u.all);
+diff --git a/net/netfilter/nft_ct_fast.c b/net/netfilter/nft_ct_fast.c
+index e684c8a9184877..ecf7b3a404be26 100644
+--- a/net/netfilter/nft_ct_fast.c
++++ b/net/netfilter/nft_ct_fast.c
+@@ -30,7 +30,7 @@ void nft_ct_get_fast_eval(const struct nft_expr *expr,
+               break;
+       }
+-      if (!ct) {
++      if (!ct || nf_ct_is_template(ct)) {
+               regs->verdict.code = NFT_BREAK;
+               return;
+       }
+-- 
+2.53.0
+
diff --git a/queue-7.0/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch b/queue-7.0/netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
new file mode 100644 (file)
index 0000000..7d9e61a
--- /dev/null
@@ -0,0 +1,113 @@
+From 0ec0c0cd655b36ccd4068a207efc97a2cc6d5b13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 23:58:31 +0200
+Subject: netfilter: synproxy: add mutex to guard hook reference counting
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
+
+As the synproxy infrastructure register netfilter hooks on-demand when a
+user adds the first iptables target or nftables expression, if done
+concurrently they can race each other.
+
+Introduce a mutex to serialize the refcount control blocks access from
+both frontends. While a per namespace mutex might be more efficient, it
+is not needed for target/expression like SYNPROXY.
+
+Fixes: ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 036c8586f49b75..ed00114f65f392 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -22,6 +22,8 @@
+ #include <net/netfilter/nf_conntrack_zones.h>
+ #include <net/netfilter/nf_synproxy.h>
++static DEFINE_MUTEX(synproxy_mutex);
++
+ unsigned int synproxy_net_id;
+ EXPORT_SYMBOL_GPL(synproxy_net_id);
+@@ -769,26 +771,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
+ int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref4 == 0) {
+               err = nf_register_net_hooks(net, ipv4_synproxy_ops,
+                                           ARRAY_SIZE(ipv4_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref4++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
+ void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref4--;
+       if (snet->hook_ref4 == 0)
+               nf_unregister_net_hooks(net, ipv4_synproxy_ops,
+                                       ARRAY_SIZE(ipv4_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
+@@ -1193,27 +1200,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
+ int
+ nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
+ {
+-      int err;
++      int err = 0;
++      mutex_lock(&synproxy_mutex);
+       if (snet->hook_ref6 == 0) {
+               err = nf_register_net_hooks(net, ipv6_synproxy_ops,
+                                           ARRAY_SIZE(ipv6_synproxy_ops));
+               if (err)
+-                      return err;
++                      goto out;
+       }
+       snet->hook_ref6++;
+-      return 0;
++out:
++      mutex_unlock(&synproxy_mutex);
++      return err;
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
+ void
+ nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
+ {
++      mutex_lock(&synproxy_mutex);
+       snet->hook_ref6--;
+       if (snet->hook_ref6 == 0)
+               nf_unregister_net_hooks(net, ipv6_synproxy_ops,
+                                       ARRAY_SIZE(ipv6_synproxy_ops));
++      mutex_unlock(&synproxy_mutex);
+ }
+ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
+ #endif /* CONFIG_IPV6 */
+-- 
+2.53.0
+
diff --git a/queue-7.0/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch b/queue-7.0/netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
new file mode 100644 (file)
index 0000000..5820474
--- /dev/null
@@ -0,0 +1,41 @@
+From 5580c67ddb11434d5f0ef9e0f713d7a31fd924d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 12:47:17 +0200
+Subject: netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
+
+With PREEMPT_RCU this triggers a splat because smp_processor_id() can be
+preempted while inside a RCU critical section. If xt_NFQUEUE target is
+invoked via nft_compat_eval() path, we are inside a RCU critical
+section.
+
+Just use the raw version instead.
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+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>
+---
+ net/netfilter/xt_NFQUEUE.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
+index 466da23e36ff47..b32d153e3a1862 100644
+--- a/net/netfilter/xt_NFQUEUE.c
++++ b/net/netfilter/xt_NFQUEUE.c
+@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+       if (info->queues_total > 1) {
+               if (info->flags & NFQ_FLAG_CPU_FANOUT) {
+-                      int cpu = smp_processor_id();
++                      int cpu = raw_smp_processor_id();
+                       queue = info->queuenum + cpu % info->queues_total;
+               } else {
+-- 
+2.53.0
+
diff --git a/queue-7.0/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch b/queue-7.0/octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch
new file mode 100644 (file)
index 0000000..068afff
--- /dev/null
@@ -0,0 +1,44 @@
+From 96dbbcd76edea442e324f5b656cbbd62041c319d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 17:07:05 +0530
+Subject: octeontx2-af: Fix initialization of mcam's entry2target_pffunc field
+
+From: Suman Ghosh <sumang@marvell.com>
+
+[ Upstream commit 9a85ec3dc28b6df246801c19e4d9bae6297a25b0 ]
+
+NPC mcam entry stores a mapping between mcam entry and target pcifunc.
+During initialization of this field, API kmalloc_array has been used which
+caused some junk values to array. Whereas, the array is expected to be
+initialized by 0. This patch fixes the same by using kcalloc instead of
+kmalloc_array.
+
+Fixes: 55307fcb9258 ("octeontx2-af: Add mbox messages to install and delete MCAM rules")
+Signed-off-by: Suman Ghosh <sumang@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/1780054625-17090-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index e28675fe189071..a0d2ed56186d8d 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -1932,8 +1932,8 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
+               goto free_entry_cntr_map;
+       /* Alloc memory for saving target device of mcam rule */
+-      mcam->entry2target_pffunc = kmalloc_array(mcam->total_entries,
+-                                                sizeof(u16), GFP_KERNEL);
++      mcam->entry2target_pffunc = kcalloc(mcam->total_entries,
++                                          sizeof(u16), GFP_KERNEL);
+       if (!mcam->entry2target_pffunc)
+               goto free_cntr_refcnt;
+-- 
+2.53.0
+
diff --git a/queue-7.0/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch b/queue-7.0/octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
new file mode 100644 (file)
index 0000000..75a0d65
--- /dev/null
@@ -0,0 +1,119 @@
+From 037ab2919e057e97e7b28c7209b5a08d42b7ab7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 10:28:53 +0530
+Subject: octeontx2-af: npc: Fix CPT channel mask in npc_install_flow
+
+From: Nithin Dabilpuram <ndabilpuram@marvell.com>
+
+[ Upstream commit 1d31eb27e570daa04f5373345f9ac98c95863be9 ]
+
+Use the CPT-aware NIX channel mask in the npc_install_flow path so that
+when the host PF installs steering rules in kernel for a VF used from
+userspace (e.g. DPDK), MCAM entries see the same channel mask semantics as
+other RX paths.
+
+Fixes: 56bcef528bd8 ("octeontx2-af: Use npc_install_flow API for promisc and broadcast entries")
+Cc: Naveen Mamindlapalli <naveenm@marvell.com>
+Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
+Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
+Link: https://patch.msgid.link/20260602045853.1558530-1-rkannoth@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |  1 +
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   | 32 +++++++++----------
+ .../marvell/octeontx2/af/rvu_npc_fs.c         |  2 +-
+ 3 files changed, 18 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index 3f76ec6c5cf3b9..e31d7bc4a0e9c2 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -1138,6 +1138,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
+                       int slot);
+ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);
+ int rvu_cpt_init(struct rvu *rvu);
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu);
+ #define NDC_AF_BANK_MASK       GENMASK_ULL(7, 0)
+ #define NDC_AF_BANK_LINE_MASK  GENMASK_ULL(31, 16)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index a0d2ed56186d8d..65aa6aeab8e782 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -599,6 +599,19 @@ void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
+                          NPC_AF_MCAMEX_BANKX_ACTION(index, bank), cfg);
+ }
++u32 rvu_get_cpt_chan_mask(struct rvu *rvu)
++{
++      /* For cn10k the upper two bits of the channel number are
++       * cpt channel number. with masking out these bits in the
++       * mcam entry, same entry used for NIX will allow packets
++       * received from cpt for parsing.
++       */
++      if (!is_rvu_otx2(rvu))
++              return NIX_CHAN_CPT_X2P_MASK;
++      else
++              return 0xFFFu;
++}
++
+ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+                                int nixlf, u64 chan, u8 *mac_addr)
+ {
+@@ -642,7 +655,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
+       eth_broadcast_addr((u8 *)&req.mask.dmac);
+       req.features = BIT_ULL(NPC_DMAC);
+       req.channel = chan;
+-      req.chan_mask = 0xFFFU;
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.intf = pfvf->nix_rx_intf;
+       req.op = action.op;
+       req.hdr.pcifunc = 0; /* AF is requester */
+@@ -712,11 +725,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
+        * mcam entry, same entry used for NIX will allow packets
+        * received from cpt for parsing.
+        */
+-      if (!is_rvu_otx2(rvu)) {
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      } else {
+-              req.chan_mask = 0xFFFU;
+-      }
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       if (chan_cnt > 1) {
+               if (!is_power_of_2(chan_cnt)) {
+@@ -887,16 +896,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
+       ether_addr_copy(req.mask.dmac, mac_addr);
+       req.features = BIT_ULL(NPC_DMAC);
+-      /* For cn10k the upper two bits of the channel number are
+-       * cpt channel number. with masking out these bits in the
+-       * mcam entry, same entry used for NIX will allow packets
+-       * received from cpt for parsing.
+-       */
+-      if (!is_rvu_otx2(rvu))
+-              req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
+-      else
+-              req.chan_mask = 0xFFFU;
+-
++      req.chan_mask = rvu_get_cpt_chan_mask(rvu);
+       req.channel = chan;
+       req.intf = pfvf->nix_rx_intf;
+       req.entry = index;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+index 1930b54e72f219..02663530368965 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+@@ -1470,7 +1470,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
+       /* ignore chan_mask in case pf func is not AF, revisit later */
+       if (!is_pffunc_af(req->hdr.pcifunc))
+-              req->chan_mask = 0xFFF;
++              req->chan_mask = rvu_get_cpt_chan_mask(rvu);
+       err = npc_check_unsupported_flows(rvu, req->features, req->intf);
+       if (err)
+-- 
+2.53.0
+
diff --git a/queue-7.0/octeontx2-pf-fix-ndc-sync-operation-errors.patch b/queue-7.0/octeontx2-pf-fix-ndc-sync-operation-errors.patch
new file mode 100644 (file)
index 0000000..d7d68eb
--- /dev/null
@@ -0,0 +1,40 @@
+From 53fb34b1d49ef5da42e5992aa39dd0ffff9a198a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 17:07:57 +0530
+Subject: octeontx2-pf: Fix NDC sync operation errors
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit a910fb8f7b9e4c566db363e6c2ec378dc7153995 ]
+
+On system reboot "rvu_nicpf 0002:03:00.0: NDC sync operation failed"
+error messages are shown, even if the operations is successful.
+This is due to wrong if error check in ndc_syc() function.
+
+Fixes: 42c45ac1419c ("octeontx2-af: Sync NIX and NPA contexts from NDC to LLC/DRAM")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/1780054677-17249-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index ee623476e5ff1a..f9fbf0c1764825 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -3473,7 +3473,7 @@ static void otx2_ndc_sync(struct otx2_nic *pf)
+       req->nix_lf_rx_sync = 1;
+       req->npa_lf_sync = 1;
+-      if (!otx2_sync_mbox_msg(mbox))
++      if (otx2_sync_mbox_msg(mbox))
+               dev_err(pf->dev, "NDC sync operation failed\n");
+       mutex_unlock(&mbox->lock);
+-- 
+2.53.0
+
diff --git a/queue-7.0/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch b/queue-7.0/pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
new file mode 100644 (file)
index 0000000..8ae1e4a
--- /dev/null
@@ -0,0 +1,58 @@
+From 558f30aae165073234f0ff1cf02b783e4b70fcfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 16:03:20 +0200
+Subject: pcnet32: stop holding device spin lock during napi_complete_done
+
+From: Oscar Maes <oscmaes92@gmail.com>
+
+[ Upstream commit 73bf3cca7de6a73f53b6a52dc3b1c82ae5667a4d ]
+
+napi_complete_done may call gro_flush_normal (though not currently, as GRO
+is unsupported at the moment), which may result in packet TX. This will
+eventually result in calling pcnet32_start_xmit - resulting in a deadlock
+while trying to re-acquire the already locked spin lock.
+
+It is safe to split the spinlock block into two, because the hardware
+registers are still protected from concurrent access, and the two blocks
+perform unrelated operations that don't need to happen atomically.
+
+Fixes: 5b2ec6f2be51 ("pcnet32: use napi_complete_done()")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260528140320.5556-1-oscmaes92@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/pcnet32.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 911808ab13a79d..4f3076d4ea34eb 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1407,8 +1407,10 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               pcnet32_restart(dev, CSR0_START);
+               netif_wake_queue(dev);
+       }
++      spin_unlock_irqrestore(&lp->lock, flags);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
++              spin_lock_irqsave(&lp->lock, flags);
+               /* clear interrupt masks */
+               val = lp->a->read_csr(ioaddr, CSR3);
+               val &= 0x00ff;
+@@ -1416,9 +1418,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
+               /* Set interrupt enable. */
+               lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
++              spin_unlock_irqrestore(&lp->lock, flags);
+       }
+-      spin_unlock_irqrestore(&lp->lock, flags);
+       return work_done;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/ptp-vclock-switch-from-rcu-to-srcu.patch b/queue-7.0/ptp-vclock-switch-from-rcu-to-srcu.patch
new file mode 100644 (file)
index 0000000..5c10212
--- /dev/null
@@ -0,0 +1,85 @@
+From 363f8146b6afbbfe5f88932fa2a41ea4d1c73ed5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 19:11:47 +0200
+Subject: ptp: vclock: Switch from RCU to SRCU
+
+From: Kurt Kanzenbach <kurt@linutronix.de>
+
+[ Upstream commit 672bd0519e27c357c43b7f8c0d653fce3817d06e ]
+
+The usage of PTP vClocks leads immediately to the following issues with
+ptp4l with LOCKDEP and DEBUG_ATOMIC_SLEEP enabled: "BUG: sleeping function
+called from invalid context".
+
+ptp_convert_timestamp() acquires a mutex_t within a RCU read section.  This
+is illegal, because acquiring a mutex_t can result in voluntary scheduling
+request which is not allowed within a RCU read section.
+
+Replace the RCU usage with SRCU where sleeping is allowed.
+
+Reported-by: Florian Zeitz <florian.zeitz@schettke.com>
+Closes: https://lore.kernel.org/all/00a8cce8-410e-4038-98af-49be6d93d7bd@schettke.com/
+Fixes: 67d93ffc0f3c ("ptp: vclock: use mutex to fix "sleep on atomic" bug")
+Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260529-vclock_rcu-v2-1-02a5531fab92@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_vclock.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
+index 915a4f6defc945..84cb527f59ccc6 100644
+--- a/drivers/ptp/ptp_vclock.c
++++ b/drivers/ptp/ptp_vclock.c
+@@ -19,6 +19,8 @@ static DEFINE_SPINLOCK(vclock_hash_lock);
+ static DEFINE_READ_MOSTLY_HASHTABLE(vclock_hash, 8);
++DEFINE_STATIC_SRCU(vclock_srcu);
++
+ static void ptp_vclock_hash_add(struct ptp_vclock *vclock)
+ {
+       spin_lock(&vclock_hash_lock);
+@@ -37,7 +39,7 @@ static void ptp_vclock_hash_del(struct ptp_vclock *vclock)
+       spin_unlock(&vclock_hash_lock);
+-      synchronize_rcu();
++      synchronize_srcu(&vclock_srcu);
+ }
+ static int ptp_vclock_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+@@ -276,14 +278,16 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+ {
+       unsigned int hash = vclock_index % HASH_SIZE(vclock_hash);
+       struct ptp_vclock *vclock;
+-      u64 ns;
+       u64 vclock_ns = 0;
++      int srcu_idx;
++      u64 ns;
+       ns = ktime_to_ns(*hwtstamp);
+-      rcu_read_lock();
++      srcu_idx = srcu_read_lock(&vclock_srcu);
+-      hlist_for_each_entry_rcu(vclock, &vclock_hash[hash], vclock_hash_node) {
++      hlist_for_each_entry_srcu(vclock, &vclock_hash[hash], vclock_hash_node,
++                                srcu_read_lock_held(&vclock_srcu)) {
+               if (vclock->clock->index != vclock_index)
+                       continue;
+@@ -294,7 +298,7 @@ ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index)
+               break;
+       }
+-      rcu_read_unlock();
++      srcu_read_unlock(&vclock_srcu, srcu_idx);
+       return ns_to_ktime(vclock_ns);
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/reapply-bnxt_en-bring-back-rtnl_lock-in-the-bnxt_ope.patch b/queue-7.0/reapply-bnxt_en-bring-back-rtnl_lock-in-the-bnxt_ope.patch
new file mode 100644 (file)
index 0000000..ccb38dd
--- /dev/null
@@ -0,0 +1,169 @@
+From 231d9e3d9d068d0908341b22ffa99cae310a5f73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 12:58:45 -0700
+Subject: Reapply "bnxt_en: bring back rtnl_lock() in the bnxt_open() path"
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit b6197b386677ae5268d4702e23849d9ad53051ad ]
+
+This reverts commit 850d9248d2eac662f869c766a598c877690c74e5.
+This reapplies commit 325eb217e41f ("bnxt_en: bring back rtnl_lock()
+in the bnxt_open() path").
+
+Breno reports a lockdep warning in bnxt. During FW reset the driver
+may end up calling netif_set_real_num_tx_queues() (if queue count
+changes), so calls to bnxt_open() still require rtnl_lock.
+
+  net/sched/sch_generic.c:1416 suspicious rcu_dereference_protected() usage!
+
+   dev_qdisc_change_real_num_tx+0x54/0xe0
+   netif_set_real_num_tx_queues+0x4ed/0xa80
+   __bnxt_open_nic+0x9cb/0x3490
+   bnxt_open+0x1cb/0x370
+   bnxt_fw_reset_task+0x80d/0x1e80
+   process_scheduled_works+0x9c1/0x13b0
+
+The reverted commit was just an optimization / experiment
+so let's go back to taking the lock.
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Link: https://lore.kernel.org/ah726OtFX-Qw3U-R@gmail.com
+Fixes: 850d9248d2ea ("Revert "bnxt_en: bring back rtnl_lock() in the bnxt_open() path"")
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20260603195845.2574426-1-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 36 ++++++++++++++++++-----
+ 1 file changed, 29 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 86e45352cec105..ff5501999b4df1 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -14290,13 +14290,28 @@ static void bnxt_unlock_sp(struct bnxt *bp)
+       netdev_unlock(bp->dev);
+ }
++/* Same as bnxt_lock_sp() with additional rtnl_lock */
++static void bnxt_rtnl_lock_sp(struct bnxt *bp)
++{
++      clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
++      rtnl_lock();
++      netdev_lock(bp->dev);
++}
++
++static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
++{
++      set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
++      netdev_unlock(bp->dev);
++      rtnl_unlock();
++}
++
+ /* Only called from bnxt_sp_task() */
+ static void bnxt_reset(struct bnxt *bp, bool silent)
+ {
+-      bnxt_lock_sp(bp);
++      bnxt_rtnl_lock_sp(bp);
+       if (test_bit(BNXT_STATE_OPEN, &bp->state))
+               bnxt_reset_task(bp, silent);
+-      bnxt_unlock_sp(bp);
++      bnxt_rtnl_unlock_sp(bp);
+ }
+ /* Only called from bnxt_sp_task() */
+@@ -14304,9 +14319,9 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
+ {
+       int i;
+-      bnxt_lock_sp(bp);
++      bnxt_rtnl_lock_sp(bp);
+       if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
+-              bnxt_unlock_sp(bp);
++              bnxt_rtnl_unlock_sp(bp);
+               return;
+       }
+       /* Disable and flush TPA before resetting the RX ring */
+@@ -14345,7 +14360,7 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
+       }
+       if (bp->flags & BNXT_FLAG_TPA)
+               bnxt_set_tpa(bp, true);
+-      bnxt_unlock_sp(bp);
++      bnxt_rtnl_unlock_sp(bp);
+ }
+ static void bnxt_fw_fatal_close(struct bnxt *bp)
+@@ -15255,15 +15270,17 @@ static void bnxt_fw_reset_task(struct work_struct *work)
+               bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING;
+               fallthrough;
+       case BNXT_FW_RESET_STATE_OPENING:
+-              while (!netdev_trylock(bp->dev)) {
++              while (!rtnl_trylock()) {
+                       bnxt_queue_fw_reset_work(bp, HZ / 10);
+                       return;
+               }
++              netdev_lock(bp->dev);
+               rc = bnxt_open(bp->dev);
+               if (rc) {
+                       netdev_err(bp->dev, "bnxt_open() failed during FW reset\n");
+                       bnxt_fw_reset_abort(bp, rc);
+                       netdev_unlock(bp->dev);
++                      rtnl_unlock();
+                       goto ulp_start;
+               }
+@@ -15283,6 +15300,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
+                       bnxt_dl_health_fw_status_update(bp, true);
+               }
+               netdev_unlock(bp->dev);
++              rtnl_unlock();
+               bnxt_ulp_start(bp);
+               bnxt_reenable_sriov(bp);
+               netdev_lock(bp->dev);
+@@ -16272,7 +16290,7 @@ static int bnxt_queue_start(struct net_device *dev,
+                  rc);
+       napi_enable_locked(&bnapi->napi);
+       bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons);
+-      bnxt_reset_task(bp, true);
++      netif_close(dev);
+       return rc;
+ }
+@@ -17116,6 +17134,7 @@ static int bnxt_resume(struct device *device)
+       struct bnxt *bp = netdev_priv(dev);
+       int rc = 0;
++      rtnl_lock();
+       netdev_lock(dev);
+       rc = pci_enable_device(bp->pdev);
+       if (rc) {
+@@ -17160,6 +17179,7 @@ static int bnxt_resume(struct device *device)
+ resume_exit:
+       netdev_unlock(bp->dev);
++      rtnl_unlock();
+       if (!rc) {
+               bnxt_ulp_start(bp);
+               bnxt_reenable_sriov(bp);
+@@ -17326,6 +17346,7 @@ static void bnxt_io_resume(struct pci_dev *pdev)
+       int err;
+       netdev_info(bp->dev, "PCI Slot Resume\n");
++      rtnl_lock();
+       netdev_lock(netdev);
+       err = bnxt_hwrm_func_qcaps(bp);
+@@ -17343,6 +17364,7 @@ static void bnxt_io_resume(struct pci_dev *pdev)
+               netif_device_attach(netdev);
+       netdev_unlock(netdev);
++      rtnl_unlock();
+       if (!err) {
+               bnxt_ulp_start(bp);
+               bnxt_reenable_sriov(bp);
+-- 
+2.53.0
+
diff --git a/queue-7.0/s390-bug-always-emit-format-word-in-__bug_entry.patch b/queue-7.0/s390-bug-always-emit-format-word-in-__bug_entry.patch
new file mode 100644 (file)
index 0000000..09cdf8b
--- /dev/null
@@ -0,0 +1,72 @@
+From b9d3af1479679b70f3a462db23ea7b21988c59ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 14:01:32 +0200
+Subject: s390/bug: Always emit format word in __BUG_ENTRY
+
+From: Jan Polensky <japo@linux.ibm.com>
+
+[ Upstream commit 3daad7f60aa92d0307fa2b2edd38c886a09902f2 ]
+
+When CONFIG_DEBUG_BUGVERBOSE is disabled, the s390 __BUG_ENTRY() macro
+omits the format string pointer, so the generated __bug_table entry no
+longer matches struct bug_entry.
+
+With HAVE_ARCH_BUG_FORMAT enabled, the generic BUG infrastructure reads
+bug_entry::format via bug_get_format(). If the format word is missing,
+subsequent fields are read from the wrong offset, which may:
+- Misinterpret flags (BUG vs WARN classification errors)
+- Fault when dereferencing a misread format pointer
+
+The root cause is that __BUG_ENTRY() delegates format word emission to
+__BUG_ENTRY_VERBOSE(), which is conditional on CONFIG_DEBUG_BUGVERBOSE.
+
+Fix this by moving the format field emission directly into __BUG_ENTRY()
+so it is always emitted unconditionally. Remove the format parameter from
+__BUG_ENTRY_VERBOSE() and keep only file/line emission conditional on
+CONFIG_DEBUG_BUGVERBOSE.
+
+Fixes: 2b71b8ab9718 ("s390/bug: Use BUG_FORMAT for DEBUG_BUGVERBOSE_DETAILED")
+Signed-off-by: Jan Polensky <japo@linux.ibm.com>
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/bug.h | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
+index 59017fd3d9358d..50a270edb02035 100644
+--- a/arch/s390/include/asm/bug.h
++++ b/arch/s390/include/asm/bug.h
+@@ -12,12 +12,11 @@
+ #if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
+ #ifdef CONFIG_DEBUG_BUGVERBOSE
+-#define __BUG_ENTRY_VERBOSE(format, file, line)                               \
+-      "       .long   " format " - .  # bug_entry::format\n"          \
++#define __BUG_ENTRY_VERBOSE(file, line)                                       \
+       "       .long   " file " - .    # bug_entry::file\n"            \
+       "       .short  " line "        # bug_entry::line\n"
+ #else
+-#define __BUG_ENTRY_VERBOSE(format, file, line)
++#define __BUG_ENTRY_VERBOSE(file, line)
+ #endif
+ #ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
+@@ -28,9 +27,10 @@
+ #define __BUG_ENTRY(format, file, line, flags, size)                  \
+               "       .section __bug_table,\"aw\"\n"                  \
+-              "1:     .long   0b - .  # bug_entry::bug_addr\n"        \
+-              __BUG_ENTRY_VERBOSE(format, file, line)                 \
+-              "       .short  "flags" # bug_entry::flags\n"           \
++              "1:     .long   0b - .          # bug_entry::bug_addr\n"\
++              "       .long   " format " - .  # bug_entry::format\n"  \
++              __BUG_ENTRY_VERBOSE(file, line)                         \
++              "       .short  "flags"         # bug_entry::flags\n"   \
+               "       .org    1b+"size"\n"                            \
+               "       .previous"
+-- 
+2.53.0
+
diff --git a/queue-7.0/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch b/queue-7.0/sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
new file mode 100644 (file)
index 0000000..36b5f1f
--- /dev/null
@@ -0,0 +1,87 @@
+From b207cd94dca6bd50bed7a762986dbff96f5ec066 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 14:11:44 -0400
+Subject: sctp: purge outqueue on stale COOKIE-ECHO handling
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit e374b22e9b07b72a25909621464ff74096151bfb ]
+
+sctp_stream_update() is only invoked when the association is moved into
+COOKIE_WAIT during association setup/reconfiguration. In this path, the
+outbound stream scheduler state (stream->out_curr) is expected to be
+clean, since no user data should have been transmitted yet unless the
+state machine has already partially progressed.
+
+However, a corner case exists in sctp_sf_do_5_2_6_stale(): when a
+Stale Cookie ERROR is received, the association is rolled back from
+COOKIE_ECHOED to COOKIE_WAIT. In this scenario, user data may already
+have been queued and even bundled with the COOKIE-ECHO chunk.
+
+During the rollback, sctp_stream_update() frees the old stream table
+and installs a new one, but it does not invalidate stream->out_curr.
+As a result, out_curr may still point to a freed sctp_stream_out
+entry from the previous stream state.
+
+Later, SCTP scheduler dequeue paths (FCFS, RR, PRIO, etc.) rely on
+stream->out_curr->ext, which can lead to use-after-free once the old
+stream state has been released via sctp_stream_free().
+
+This results in crashes such as (reported by Yuqi):
+
+  BUG: KASAN: slab-use-after-free in sctp_sched_fcfs_dequeue+0x13a/0x140
+  Read of size 8 at addr ff1100004d4d3208 by task mini_poc/9312
+  CPU: 1 UID: 1001 PID: 9312 Comm: mini_poc Not tainted
+     7.1.0-rc1-00305-gbd3a4795d574 #5 PREEMPT(full)
+   sctp_sched_fcfs_dequeue+0x13a/0x140
+   sctp_outq_flush+0x1603/0x33e0
+   sctp_do_sm+0x31c9/0x5d30
+   sctp_assoc_bh_rcv+0x392/0x6f0
+   sctp_inq_push+0x1db/0x270
+   sctp_rcv+0x138d/0x3c10
+
+Fix this by fully purging the association outqueue when handling the
+Stale Cookie case. This ensures all pending transmit and retransmit
+state is dropped, and any scheduler cached pointers are invalidated,
+making it safe to rebuild stream state during COOKIE_WAIT restart.
+
+Updating only stream->out_curr would be insufficient, since queued
+and retransmittable data would still reference the old stream state and
+trigger later use-after-free in dequeue paths.
+
+Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Yuqi Xu <xuyq21@lenovo.com>
+Reported-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/94318159b9052907a6cbb7256aee8b5f8dfbfccb.1780510304.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 8e89a870780c49..9b23c11cbb9ea4 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2598,11 +2598,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+-      /* If we've sent any data bundled with COOKIE-ECHO we will need to
+-       * resend
+-       */
+-      sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
+-                      SCTP_TRANSPORT(asoc->peer.primary_path));
++      sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+       /* Cast away the const modifier, as we want to just
+        * rerun it through as a sideffect.
+-- 
+2.53.0
+
diff --git a/queue-7.0/sctp-validate-cached-peer-init-chunk-length-in-cooki.patch b/queue-7.0/sctp-validate-cached-peer-init-chunk-length-in-cooki.patch
new file mode 100644 (file)
index 0000000..5f72b61
--- /dev/null
@@ -0,0 +1,61 @@
+From b7544ab193ada0d438c1a741d18cb532aaf12b7c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 21:06:06 -0400
+Subject: sctp: validate cached peer INIT chunk length in COOKIE_ECHO
+ processing
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 0861615c28de668669d748ef4eb913ea9262d13b ]
+
+When a listening SCTP server processes a COOKIE_ECHO chunk, the cached
+peer INIT chunk embedded after the cookie is parsed and its parameters
+are later walked by sctp_process_init() using sctp_walk_params().
+
+However, the chunk header length of this cached INIT chunk was not
+validated against the remaining buffer in the COOKIE_ECHO payload. If
+the length field is inflated, the parameter walk can run beyond the
+actual received data, leading to out-of-bounds reads and potential
+memory corruption during later parameter handling (e.g. STATE_COOKIE
+processing and kmemdup() copies).
+
+Add a bounds check in sctp_unpack_cookie() to ensure the cached INIT
+chunk length does not exceed the available data in the COOKIE_ECHO
+buffer before it is used.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: Brian Geffon <bgeffon@google.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/eb60825fa22d6f9e663c7d4dbb69f397b5d34d42.1780362366.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_make_chunk.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 2c0017d058d409..9014b095f52ddb 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -1730,6 +1730,7 @@ struct sctp_association *sctp_unpack_cookie(
+       struct sctp_signed_cookie *cookie;
+       struct sk_buff *skb = chunk->skb;
+       struct sctp_cookie *bear_cookie;
++      struct sctp_chunkhdr *ch;
+       enum sctp_scope scope;
+       unsigned int len;
+       ktime_t kt;
+@@ -1759,6 +1760,10 @@ struct sctp_association *sctp_unpack_cookie(
+       cookie = chunk->subh.cookie_hdr;
+       bear_cookie = &cookie->c;
++      ch = (struct sctp_chunkhdr *)(bear_cookie + 1);
++      if (ntohs(ch->length) > len - fixed_size)
++              goto malformed;
++
+       /* Verify the cookie's MAC, if cookie authentication is enabled. */
+       if (sctp_sk(ep->base.sk)->cookie_auth_enable) {
+               u8 mac[SHA256_DIGEST_SIZE];
+-- 
+2.53.0
+
index e1fbbdd17163550afa42ced94a93089b235e3245..92f100faeb3d13327424f0b61a1d8bf96026c480 100644 (file)
@@ -1 +1,71 @@
 bpf-free-reuseport-cbpf-prog-after-rcu-grace-period.patch
+tee-optee-prevent-use-after-free-when-the-client-exi.patch
+soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch
+arm64-dts-qcom-x1-dell-thena-remove-i2c20-battery-sm.patch
+arm-dts-microchip-sam9x7-fix-gmac-clock-configuratio.patch
+soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch
+tee-fix-tee_ioctl_object_invoke_arg-padding.patch
+tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch
+s390-bug-always-emit-format-word-in-__bug_entry.patch
+arm-dts-gemini-fix-partition-offsets.patch
+erofs-fix-use-after-free-on-sbi-sync_decompress.patch
+wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch
+ksmbd-fix-null-deref-of-opinfo-conn-in-oplock-lease-.patch
+netfilter-xt_nfqueue-prefer-raw_smp_processor_id.patch
+ipvs-clear-the-svc-scheduler-ptr-early-on-edit.patch
+netfilter-synproxy-add-mutex-to-guard-hook-reference.patch
+netfilter-conntrack_irc-fix-possible-out-of-bounds-r.patch
+netfilter-nft_ct-bail-out-on-template-ct-in-get-eval.patch
+netfilter-bridge-make-ebt_snat-arp-rewrite-writable.patch
+dm-cache-policy-smq-check-allocation-under-invalidat.patch
+net-sched-act_api-use-rcu-with-deferred-freeing-for-.patch
+6lowpan-fix-off-by-one-in-multicast-context-address-.patch
+l2tp-pppol2tp-hold-reference-to-session-in-pppol2tp_.patch
+devlink-release-nested-relation-on-devlink-free.patch
+drm-imx-fix-three-kernel-doc-warnings-in-dcss-scaler.patch
+wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch
+pcnet32-stop-holding-device-spin-lock-during-napi_co.patch
+net-annotate-sk-sk_write_space-for-udp-sockmap.patch
+tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch
+hsr-remove-warn_once-in-hsr_addr_is_self.patch
+net-garp-fix-unsigned-integer-underflow-in-garp_pdu_.patch
+net-lan743x-permit-vlan-tagged-packets-up-to-configu.patch
+net-fec-fix-pinctrl-default-state-restore-order-on-r.patch
+ipv6-anycast-insert-aca-into-global-hash-under-idev-.patch
+wifi-fix-leak-if-split-6-ghz-scanning-fails.patch
+wifi-cfg80211-add-support-to-handle-incumbent-signal.patch
+wifi-nl80211-split-out-uhr-operation-information.patch
+wifi-cfg80211-enforce-he-eht-cap-oper-consistency.patch
+bluetooth-rfcomm-hold-listener-socket-in-rfcomm_conn.patch
+bluetooth-mgmt-validate-advertising-tlv-before-type-.patch
+bluetooth-rfcomm-validate-skb-length-in-mcc-handlers.patch
+bluetooth-bnep-fix-incorrect-length-parsing-in-bnep_.patch
+bluetooth-bnep-reject-short-frames-before-parsing.patch
+bluetooth-fix-memory-leak-in-error-path-of-hci_alloc.patch
+bluetooth-iso-fix-not-releasing-hdev-reference-on-is.patch
+bluetooth-iso-fix-a-use-after-free-of-the-hci_conn-p.patch
+bluetooth-iso-fix-data-race-on-iso_pi-fields-in-hci_.patch
+bluetooth-sco-fix-data-race-on-sco_pi-fields-in-sco_.patch
+bluetooth-mgmt-fix-backward-compatibility-with-users.patch
+xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch
+octeontx2-pf-fix-ndc-sync-operation-errors.patch
+octeontx2-af-fix-initialization-of-mcam-s-entry2targ.patch
+af_unix-fix-inq_len-update-problem-in-partial-read.patch
+ipv4-restrict-ipopt_ssrr-and-ipopt_lsrr-options.patch
+ptp-vclock-switch-from-rcu-to-srcu.patch
+net-airoha-fix-use-after-free-in-metadata-dst-teardo.patch
+net-ethernet-mtk_eth_soc-fix-use-after-free-in-metad.patch
+geneve-fix-length-used-in-gro-hint-udp-checksum-adju.patch
+net-sched-fix-pedit-partial-cow-leading-to-page-cach.patch
+sctp-validate-cached-peer-init-chunk-length-in-cooki.patch
+octeontx2-af-npc-fix-cpt-channel-mask-in-npc_install.patch
+vxlan-vnifilter-send-notification-on-vni-add.patch
+vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
+ipv6-mcast-fix-use-after-free-when-processing-mld-qu.patch
+ieee802154-6lowpan-only-accept-ipv6-packets-in-lowpa.patch
+net-802-mrp-fix-vector-attribute-parsing-in-mrp_pdu_.patch
+bonding-annotate-data-races-arcound-churn-variables.patch
+sctp-purge-outqueue-on-stale-cookie-echo-handling.patch
+fwctl-bnxt_en-move-common-definitions-to-include-lin.patch
+fwctl-bnxt_en-refactor-aux-bus-functions-to-be-more-.patch
+reapply-bnxt_en-bring-back-rtnl_lock-in-the-bnxt_ope.patch
diff --git a/queue-7.0/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch b/queue-7.0/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch
new file mode 100644 (file)
index 0000000..02fac34
--- /dev/null
@@ -0,0 +1,87 @@
+From 86b585f24db968ee39fa9e12b6eb2b44b2864b55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Apr 2026 17:29:19 +0530
+Subject: soc: qcom: ice: Allow explicit votes on 'iface' clock for ICE
+
+From: Harshal Dev <harshal.dev@oss.qualcomm.com>
+
+[ Upstream commit 0d5dc5818191b55e4364d04b1b898a14a2ccac38 ]
+
+Since Qualcomm inline-crypto engine (ICE) is now a dedicated driver
+de-coupled from the QCOM UFS driver, it explicitly votes for its required
+clocks during probe. For scenarios where the 'clk_ignore_unused' flag is
+not passed on the kernel command line, to avoid potential unclocked ICE
+hardware register access during probe the ICE driver should additionally
+vote on the 'iface' clock.
+Also update the suspend and resume callbacks to handle un-voting and voting
+on the 'iface' clock.
+
+Fixes: 2afbf43a4aec6 ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver")
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Reviewed-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-2-5ccf5d7e2846@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index b203bc685cadd2..bf4ab2d9e5c036 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -108,6 +108,7 @@ struct qcom_ice {
+       void __iomem *base;
+       struct clk *core_clk;
++      struct clk *iface_clk;
+       bool use_hwkm;
+       bool hwkm_init_complete;
+       u8 hwkm_version;
+@@ -312,8 +313,13 @@ int qcom_ice_resume(struct qcom_ice *ice)
+       err = clk_prepare_enable(ice->core_clk);
+       if (err) {
+-              dev_err(dev, "failed to enable core clock (%d)\n",
+-                      err);
++              dev_err(dev, "Failed to enable core clock: %d\n", err);
++              return err;
++      }
++
++      err = clk_prepare_enable(ice->iface_clk);
++      if (err) {
++              dev_err(dev, "Failed to enable iface clock: %d\n", err);
+               return err;
+       }
+       qcom_ice_hwkm_init(ice);
+@@ -323,6 +329,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
+ int qcom_ice_suspend(struct qcom_ice *ice)
+ {
++      clk_disable_unprepare(ice->iface_clk);
+       clk_disable_unprepare(ice->core_clk);
+       ice->hwkm_init_complete = false;
+@@ -579,11 +586,17 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
+       engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_optional_enabled(dev, "ice");
++      if (!engine->core_clk)
++              engine->core_clk = devm_clk_get_optional_enabled(dev, "core");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_enabled(dev, NULL);
+       if (IS_ERR(engine->core_clk))
+               return ERR_CAST(engine->core_clk);
++      engine->iface_clk = devm_clk_get_optional_enabled(dev, "iface");
++      if (IS_ERR(engine->iface_clk))
++              return ERR_CAST(engine->iface_clk);
++
+       if (!qcom_ice_check_supported(engine))
+               return ERR_PTR(-EOPNOTSUPP);
+-- 
+2.53.0
+
diff --git a/queue-7.0/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch b/queue-7.0/soc-qcom-ice-return-enodev-if-the-ice-platform-devic.patch
new file mode 100644 (file)
index 0000000..c3e0509
--- /dev/null
@@ -0,0 +1,44 @@
+From 6a8f0b614ab8736c07586f8a25225ff7f2f3ad53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 May 2026 19:22:18 +0530
+Subject: soc: qcom: ice: Return -ENODEV if the ICE platform device is not
+ found
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+
+[ Upstream commit 5a4dc805a80e6fe303d6a4748cd451ea15987ffd ]
+
+By the time the consumer driver calls devm_of_qcom_ice_get(), all the
+platform devices for ICE nodes would've been created by
+of_platform_default_populate().
+
+So for the absence of any platform device, -ENODEV should not returned, not
+-EPROBE_DEFER.
+
+Fixes: 2afbf43a4aec ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver")
+Tested-by: Sumit Garg <sumit.garg@oss.qualcomm.com> # OP-TEE as TZ
+Acked-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260518-qcom-ice-fix-v7-2-2a595382185b@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index bf4ab2d9e5c036..6520e146d2ce06 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -657,7 +657,7 @@ static struct qcom_ice *of_qcom_ice_get(struct device *dev)
+       pdev = of_find_device_by_node(node);
+       if (!pdev) {
+               dev_err(dev, "Cannot find device node %s\n", node->name);
+-              return ERR_PTR(-EPROBE_DEFER);
++              return ERR_PTR(-ENODEV);
+       }
+       ice = platform_get_drvdata(pdev);
+-- 
+2.53.0
+
diff --git a/queue-7.0/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch b/queue-7.0/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch
new file mode 100644 (file)
index 0000000..53a9584
--- /dev/null
@@ -0,0 +1,118 @@
+From 7a4f884b617eec97780f449af085df8c8b17aff7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 18:20:55 +0000
+Subject: tcp: Add preempt_{disable,enable}_nested() in reqsk_queue_hash_req().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit e10902df24488ca722303133acfc82490f7d59ad ]
+
+syzbot reported a weird reqsk->rsk_refcnt underflow in
+__inet_csk_reqsk_queue_drop().
+
+The captured reqsk_put() in __inet_csk_reqsk_queue_drop()
+is called only when it successfully removes reqsk from ehash.
+
+Moreover, reqsk_timer_handler() calls another reqsk_put()
+after that.
+
+This indicates that the reqsk was missing both refcnts for
+ehash and the timer itself.
+
+Since all the syzbot reports had PREEMPT_RT enabled, the only
+possible scenario is that reqsk_queue_hash_req() is preempted
+after mod_timer() and before refcount_set(), and then the timer
+triggered after 1s aborts the reqsk due to its listener's close().
+
+Let's wrap mod_timer() and refcount_set() with
+preempt_disable_nested() and preempt_enable_nested().
+
+Note that inet_ehash_insert() holds the normal spin_lock()
+(mutex in PREEMPT_RT), so it must be called outside of
+preempt_disable_nested(), but this is fine.
+
+The lookup path just ignores 0 sk_refcnt entries in ehash
+and tries to create another reqsk, but this will fail at
+inet_ehash_insert().
+
+[0]:
+refcount_t: underflow; use-after-free.
+WARNING: lib/refcount.c:28 at refcount_warn_saturate+0xb2/0x110 lib/refcount.c:28, CPU#0: ktimers/0/16
+Modules linked in:
+CPU: 0 UID: 0 PID: 16 Comm: ktimers/0 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:refcount_warn_saturate+0xb2/0x110 lib/refcount.c:28
+Code: e4 7d d1 0a 67 48 0f b9 3a eb 4a e8 38 3d 23 fd 48 8d 3d e1 7d d1 0a 67 48 0f b9 3a eb 37 e8 25 3d 23 fd 48 8d 3d de 7d d1 0a <67> 48 0f b9 3a eb 24 e8 12 3d 23 fd 48 8d 3d db 7d d1 0a 67 48 0f
+RSP: 0000:ffffc90000157948 EFLAGS: 00010246
+RAX: ffffffff84a1301b RBX: 0000000000000003 RCX: ffff88801ca98000
+RDX: 0000000000000100 RSI: 0000000000000000 RDI: ffffffff8f72ae00
+RBP: ffffffff99ae3b01 R08: ffff88801ca98000 R09: 0000000000000005
+R10: 0000000000000100 R11: 0000000000000004 R12: ffff8880425ef568
+R13: ffff8880425ef4f8 R14: ffff8880425ef578 R15: 0000000000000000
+FS:  0000000000000000(0000) GS:ffff888126386000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f7b46710e9c CR3: 000000000dbb6000 CR4: 00000000003526f0
+Call Trace:
+ <TASK>
+ __refcount_sub_and_test include/linux/refcount.h:400 [inline]
+ __refcount_dec_and_test include/linux/refcount.h:432 [inline]
+ refcount_dec_and_test include/linux/refcount.h:450 [inline]
+ reqsk_put include/net/request_sock.h:136 [inline]
+ __inet_csk_reqsk_queue_drop+0x3ce/0x440 net/ipv4/inet_connection_sock.c:1007
+ reqsk_timer_handler+0x651/0xdf0 net/ipv4/inet_connection_sock.c:1137
+ call_timer_fn+0x192/0x5e0 kernel/time/timer.c:1748
+ expire_timers kernel/time/timer.c:1799 [inline]
+ __run_timers kernel/time/timer.c:2374 [inline]
+ __run_timer_base+0x6a3/0x9f0 kernel/time/timer.c:2386
+ run_timer_base kernel/time/timer.c:2395 [inline]
+ run_timer_softirq+0x67/0x170 kernel/time/timer.c:2403
+ handle_softirqs+0x1de/0x6d0 kernel/softirq.c:622
+ __do_softirq kernel/softirq.c:656 [inline]
+ run_ktimerd+0x69/0x100 kernel/softirq.c:1151
+ smpboot_thread_fn+0x541/0xa50 kernel/smpboot.c:160
+ kthread+0x388/0x470 kernel/kthread.c:436
+ ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
+ </TASK>
+
+Fixes: d2d6422f8bd1 ("x86: Allow to enable PREEMPT_RT.")
+Reported-by: syzbot+e809069bc15f26300526@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a1a7bcf.0a9e871e.332604.000b.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260601182101.3183993-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index f1988fd503540d..d9f6c8d4d7e63a 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -1151,6 +1151,9 @@ static bool reqsk_queue_hash_req(struct request_sock *req)
+       /* The timer needs to be setup after a successful insertion. */
+       req->timeout = tcp_timeout_init((struct sock *)req);
+       timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED);
++
++      preempt_disable_nested();
++
+       mod_timer(&req->rsk_timer, jiffies + req->timeout);
+       /* before letting lookups find us, make sure all req fields
+@@ -1158,6 +1161,9 @@ static bool reqsk_queue_hash_req(struct request_sock *req)
+        */
+       smp_wmb();
+       refcount_set(&req->rsk_refcnt, 2 + 1);
++
++      preempt_enable_nested();
++
+       return true;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/tee-fix-tee_ioctl_object_invoke_arg-padding.patch b/queue-7.0/tee-fix-tee_ioctl_object_invoke_arg-padding.patch
new file mode 100644 (file)
index 0000000..4b33d7e
--- /dev/null
@@ -0,0 +1,44 @@
+From b4a13900819795d886fdab77d8ddb3a535981e2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Dec 2025 11:17:23 +0100
+Subject: tee: fix tee_ioctl_object_invoke_arg padding
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit c15d7a2a11ea055bcecc0b538ae8ba79475637f9 ]
+
+The tee_ioctl_object_invoke_arg structure has padding on some
+architectures but not on x86-32 and a few others:
+
+include/linux/tee.h:474:32: error: padding struct to align 'params' [-Werror=padded]
+
+I expect that all current users of this are on architectures that do
+have implicit padding here (arm64, arm, x86, riscv), so make the padding
+explicit in order to avoid surprises if this later gets used elsewhere.
+
+Fixes: d5b8b0fa1775 ("tee: add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
+Tested-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/tee.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
+index cab5cadca8ef99..5203977ed35d1d 100644
+--- a/include/uapi/linux/tee.h
++++ b/include/uapi/linux/tee.h
+@@ -470,6 +470,7 @@ struct tee_ioctl_object_invoke_arg {
+       __u32 op;
+       __u32 ret;
+       __u32 num_params;
++      __u32 :32;
+       /* num_params tells the actual number of element in params */
+       struct tee_ioctl_param params[];
+ };
+-- 
+2.53.0
+
diff --git a/queue-7.0/tee-optee-prevent-use-after-free-when-the-client-exi.patch b/queue-7.0/tee-optee-prevent-use-after-free-when-the-client-exi.patch
new file mode 100644 (file)
index 0000000..a9112a9
--- /dev/null
@@ -0,0 +1,287 @@
+From 6247c1e67129ea3d63898c3959bcf6e6b5a2e824 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 14:24:06 -0800
+Subject: tee: optee: prevent use-after-free when the client exits before the
+ supplicant
+
+From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+
+[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
+
+Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the
+client wait as killable so it can be interrupted during shutdown or
+after a supplicant crash. This changes the original lifetime expectations:
+the client task can now terminate while the supplicant is still processing
+its request.
+
+If the client exits first it removes the request from its queue and
+kfree()s it, while the request ID remains in supp->idr. A subsequent
+lookup on the supplicant path then dereferences freed memory, leading to
+a use-after-free.
+
+Serialise access to the request with supp->mutex:
+
+  * Hold supp->mutex in optee_supp_recv() and optee_supp_send() while
+    looking up and touching the request.
+  * Let optee_supp_thrd_req() notice that the client has terminated and
+    signal optee_supp_send() accordingly.
+
+With these changes the request cannot be freed while the supplicant still
+has a reference, eliminating the race.
+
+Fixes: 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop")
+Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Tested-by: Ox Yeh <ox.yeh@mediatek.com>
+Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
+index a3d11b1f90fa55..06747e90c2309b 100644
+--- a/drivers/tee/optee/supp.c
++++ b/drivers/tee/optee/supp.c
+@@ -10,7 +10,11 @@
+ struct optee_supp_req {
+       struct list_head link;
++      int id;
++
+       bool in_queue;
++      bool processed;
++
+       u32 func;
+       u32 ret;
+       size_t num_params;
+@@ -19,6 +23,9 @@ struct optee_supp_req {
+       struct completion c;
+ };
++/* It is temporary request used for revoked pending request in supp->idr. */
++#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF))
++
+ void optee_supp_init(struct optee_supp *supp)
+ {
+       memset(supp, 0, sizeof(*supp));
+@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp)
+ {
+       int id;
+       struct optee_supp_req *req;
+-      struct optee_supp_req *req_tmp;
+       mutex_lock(&supp->mutex);
+-      /* Abort all request retrieved by supplicant */
++      /* Abort all request */
+       idr_for_each_entry(&supp->idr, req, id) {
+               idr_remove(&supp->idr, id);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
+-              complete(&req->c);
+-      }
++              /* Skip if request was already marked invalid */
++              if (IS_ERR(req))
++                      continue;
+-      /* Abort all queued requests */
+-      list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+-              list_del(&req->link);
+-              req->in_queue = false;
++              /* For queued requests where supplicant has not seen it */
++              if (req->in_queue) {
++                      list_del(&req->link);
++                      req->in_queue = false;
++              }
++
++              req->processed = true;
+               req->ret = TEEC_ERROR_COMMUNICATION;
+               complete(&req->c);
+       }
+@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       /* Insert the request in the request list */
+       mutex_lock(&supp->mutex);
++      req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
++      if (req->id < 0) {
++              mutex_unlock(&supp->mutex);
++              kfree(req);
++              return TEEC_ERROR_OUT_OF_MEMORY;
++      }
++
+       list_add_tail(&req->link, &supp->reqs);
+       req->in_queue = true;
++      req->processed = false;
+       mutex_unlock(&supp->mutex);
+       /* Tell an eventual waiter there's a new request */
+@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+       if (wait_for_completion_killable(&req->c)) {
+               mutex_lock(&supp->mutex);
+               if (req->in_queue) {
++                      /* Supplicant has not seen this request yet. */
++                      idr_remove(&supp->idr, req->id);
+                       list_del(&req->link);
+                       req->in_queue = false;
++
++                      ret = TEEC_ERROR_COMMUNICATION;
++              } else if (req->processed) {
++                      /*
++                       * Supplicant has processed this request. Ignore the
++                       * kill signal for now and submit the result. req is not
++                       * in supp->reqs (removed by supp_pop_entry()) nor in
++                       * supp->idr (removed by supp_pop_req()).
++                       */
++                      ret = req->ret;
++              } else {
++                      /*
++                       * Supplicant is in the middle of processing this
++                       * request. Replace req with INVALID_REQ_PTR so that
++                       * the ID remains busy, causing optee_supp_send() to
++                       * fail on the next call to supp_pop_req() with this ID.
++                       */
++                      idr_replace(&supp->idr, INVALID_REQ_PTR, req->id);
++                      ret = TEEC_ERROR_COMMUNICATION;
+               }
++
+               mutex_unlock(&supp->mutex);
+-              req->ret = TEEC_ERROR_COMMUNICATION;
++      } else {
++              ret = req->ret;
+       }
+-      ret = req->ret;
+       kfree(req);
+       return ret;
+ }
+ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+-                                            int num_params, int *id)
++                                            int num_params)
+ {
+       struct optee_supp_req *req;
+@@ -153,10 +192,6 @@ static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
+               return ERR_PTR(-EINVAL);
+       }
+-      *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+-      if (*id < 0)
+-              return ERR_PTR(-ENOMEM);
+-
+       list_del(&req->link);
+       req->in_queue = false;
+@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       struct optee_supp_req *req = NULL;
+-      int id;
+       size_t num_meta;
+       int rc;
+@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       while (true) {
+               mutex_lock(&supp->mutex);
+-              req = supp_pop_entry(supp, *num_params - num_meta, &id);
++              req = supp_pop_entry(supp, *num_params - num_meta);
++              if (req)
++                      break; /* Keep mutex held. */
+               mutex_unlock(&supp->mutex);
+-              if (req) {
+-                      if (IS_ERR(req))
+-                              return PTR_ERR(req);
+-                      break;
+-              }
+-
+               /*
+                * If we didn't get a request we'll block in
+                * wait_for_completion() to avoid needless spinning.
+@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                       return -ERESTARTSYS;
+       }
++      /* supp->mutex held and req != NULL. */
++
++      if (IS_ERR(req)) {
++              mutex_unlock(&supp->mutex);
++              return PTR_ERR(req);
++      }
++
+       if (num_meta) {
+               /*
+                * tee-supplicant support meta parameters -> requsts can be
+@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                */
+               param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+                             TEE_IOCTL_PARAM_ATTR_META;
+-              param->u.value.a = id;
++              param->u.value.a = req->id;
+               param->u.value.b = 0;
+               param->u.value.c = 0;
+       } else {
+-              mutex_lock(&supp->mutex);
+-              supp->req_id = id;
+-              mutex_unlock(&supp->mutex);
++              supp->req_id = req->id;
+       }
+       *func = req->func;
+@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+       memcpy(param + num_meta, req->param,
+              sizeof(struct tee_param) * req->num_params);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+       if (!req)
+               return ERR_PTR(-ENOENT);
++      /* optee_supp_thrd_req() already returned to optee. */
++      if (IS_ERR(req))
++              goto failed_req;
++
+       if ((num_params - nm) != req->num_params)
+               return ERR_PTR(-EINVAL);
++      *num_meta = nm;
++failed_req:
+       idr_remove(&supp->idr, id);
+       supp->req_id = -1;
+-      *num_meta = nm;
+       return req;
+ }
+@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+       mutex_lock(&supp->mutex);
+       req = supp_pop_req(supp, num_params, param, &num_meta);
+-      mutex_unlock(&supp->mutex);
+-
+       if (IS_ERR(req)) {
+-              /* Something is wrong, let supplicant restart. */
++              mutex_unlock(&supp->mutex);
++              /* Something is wrong, let supplicant handel it. */
+               return PTR_ERR(req);
+       }
+@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+               }
+       }
+       req->ret = ret;
+-
++      req->processed = true;
+       /* Let the requesting thread continue */
+       complete(&req->c);
++      mutex_unlock(&supp->mutex);
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch b/queue-7.0/tee-qcomtee-add-missing-va_end-in-early-return-qcomt.patch
new file mode 100644 (file)
index 0000000..487154f
--- /dev/null
@@ -0,0 +1,47 @@
+From da747286eb5a8b75af6f5ca36a36e5ccb1a4acad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 09:05:28 +0700
+Subject: tee: qcomtee: add missing va_end in early return
+ qcomtee_object_user_init()
+
+From: Robertus Diawan Chris <robertusdchris@gmail.com>
+
+[ Upstream commit 471c18323dfdfe7844e193b896a9267ae23a1026 ]
+
+qcomtee_object_user_init() is a variadic function and when the function
+return because there's no dispatch callback in QCOMTEE_OBJECT_TYPE_CB
+case, there's no va_end to cleanup "ap" object initialized by va_start
+and that can cause undefined behavior. So make sure to use va_end before
+returning the error code when there's no dispatch callback.
+
+This is reported by Coverity Scan as "Missing varargs init or cleanup".
+
+Fixes: d6e290837e50 ("tee: add Qualcomm TEE driver")
+Signed-off-by: Robertus Diawan Chris <robertusdchris@gmail.com>
+Reviewed-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/qcomtee/core.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tee/qcomtee/core.c b/drivers/tee/qcomtee/core.c
+index b1cb50e434f00a..60fe3b5776e36d 100644
+--- a/drivers/tee/qcomtee/core.c
++++ b/drivers/tee/qcomtee/core.c
+@@ -306,8 +306,10 @@ int qcomtee_object_user_init(struct qcomtee_object *object,
+               break;
+       case QCOMTEE_OBJECT_TYPE_CB:
+               object->ops = ops;
+-              if (!object->ops->dispatch)
+-                      return -EINVAL;
++              if (!object->ops->dispatch) {
++                      ret = -EINVAL;
++                      break;
++              }
+               /* If failed, "no-name". */
+               object->name = kvasprintf_const(GFP_KERNEL, fmt, ap);
+-- 
+2.53.0
+
diff --git a/queue-7.0/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch b/queue-7.0/vxlan-vnifilter-fix-spurious-notification-on-vni-upd.patch
new file mode 100644 (file)
index 0000000..e5037e8
--- /dev/null
@@ -0,0 +1,55 @@
+From 6852220ac7e18e2f200f92323ef92a14c22c3c35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:37 -0700
+Subject: vxlan: vnifilter: fix spurious notification on VNI update
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit 84683b5b60c7274e2c8f7f413d39d78d3db5540f ]
+
+When a VNI is re-added with the same attributes (e.g. same group or no
+group), vxlan_vni_update() sends a spurious RTM_NEWTUNNEL notification
+even though nothing changed.
+
+The bug is that 'if (changed)' tests whether the pointer is non-NULL,
+not the bool value it points to. Since every caller passes a valid
+pointer, the condition is always true and the notification fires
+unconditionally.
+
+Fix by dereferencing the pointer: 'if (*changed)'.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100
+ # bridge vni add vni 1000 dev vxlan100  # spurious notification
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-3-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index f2a202d468928c..3e76f4e210944f 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -661,7 +661,7 @@ static int vxlan_vni_update(struct vxlan_dev *vxlan,
+       if (ret)
+               return ret;
+-      if (changed)
++      if (*changed)
+               vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return 0;
+-- 
+2.53.0
+
diff --git a/queue-7.0/vxlan-vnifilter-send-notification-on-vni-add.patch b/queue-7.0/vxlan-vnifilter-send-notification-on-vni-add.patch
new file mode 100644 (file)
index 0000000..7aaae8d
--- /dev/null
@@ -0,0 +1,69 @@
+From 2907008a537e88db2dadbd21efd1e07ac37e4499 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 11:51:36 -0700
+Subject: vxlan: vnifilter: send notification on VNI add
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit aa6ca1c5c338907817374b59f7551fd855a88754 ]
+
+When a new VNI is added to a vxlan device with vnifilter enabled,
+no RTM_NEWTUNNEL notification is sent to userspace. This means
+'bridge monitor vni' never shows VNI add events, even though
+VNI delete events are reported correctly.
+
+The bug is in vxlan_vni_add(), where the notification is guarded by
+'if (changed)'. The 'changed' flag is set by vxlan_vni_update_group()
+only when the multicast group or remote IP is modified, but for a
+new VNI added without a group (e.g. in L3 VxLAN interface scenarios),
+the function returns early without setting changed=true. Since this
+is a new VNI, the notification should be sent unconditionally.
+
+The notification is not guarded by the return value of
+vxlan_vni_update_group() because, at this point, the VNI has already
+been inserted into the hash table and list with no rollback on error.
+The VNI will be visible in 'bridge vni show' regardless, so userspace
+should be informed. This is consistent with vxlan_vni_del() which also
+notifies unconditionally.
+
+The 'if (changed)' guard remains correct in vxlan_vni_update(), which
+handles the case where a VNI already exists and is being re-added --
+there, we only want to notify if the group/remote actually changed.
+
+Reproducer:
+
+ # ip link add vxlan100 type vxlan dstport 4789 local 10.0.0.1 \
+      nolearning external vnifilter
+ # ip link set vxlan100 up
+ # bridge monitor vni &
+ # bridge vni add vni 1000 dev vxlan100    # no notification
+ # bridge vni delete vni 1000 dev vxlan100 # notification received
+
+Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
+Reported-by: Chirag Shah <chirag@nvidia.com>
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20260602185138.253265-2-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_vnifilter.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index 2042369379ffc6..f2a202d468928c 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -759,8 +759,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+       err = vxlan_vni_update_group(vxlan, vninode, group, true, &changed,
+                                    extack);
+-      if (changed)
+-              vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
++      vxlan_vnifilter_notify(vxlan, vninode, RTM_NEWTUNNEL);
+       return err;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/wifi-cfg80211-add-support-to-handle-incumbent-signal.patch b/queue-7.0/wifi-cfg80211-add-support-to-handle-incumbent-signal.patch
new file mode 100644 (file)
index 0000000..04c92c3
--- /dev/null
@@ -0,0 +1,206 @@
+From ee5da4bbc2e26efe9ae7f6395268d89008d72b48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Feb 2026 08:50:26 +0530
+Subject: wifi: cfg80211: add support to handle incumbent signal detected event
+ from mac80211/driver
+
+From: Hari Chandrakanthan <quic_haric@quicinc.com>
+
+[ Upstream commit 6a584e336cefb230e2d981a464f4d85562eb750c ]
+
+When any incumbent signal is detected by an AP/mesh interface operating
+in 6 GHz band, FCC mandates the AP/mesh to vacate the channels affected
+by it [1].
+
+Add a new API cfg80211_incumbent_signal_notify() that can be used
+by mac80211 or drivers to notify the higher layers about the signal
+interference event with the interference bitmap in which each bit
+denotes the affected 20 MHz in the operating channel.
+
+Add support for the new nl80211 event and nl80211 attribute as well to
+notify userspace on the details about the interference event. Userspace is
+expected to process it and take further action - vacate the channel, or
+reduce the bandwidth.
+
+[1] - https://apps.fcc.gov/kdb/GetAttachment.html?id=nXQiRC%2B4mfiA54Zha%2BrW4Q%3D%3D&desc=987594%20D02%20U-NII%206%20GHz%20EMC%20Measurement%20v03&tracking_number=277034
+
+Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
+Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260216032027.2310956-2-amith.a@oss.qualcomm.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Stable-dep-of: cb9959ab5f99 ("wifi: cfg80211: enforce HE/EHT cap/oper consistency")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/cfg80211.h       | 23 +++++++++++++++++++++
+ include/uapi/linux/nl80211.h | 19 +++++++++++++++++
+ net/wireless/nl80211.c       | 40 ++++++++++++++++++++++++++++++++++++
+ net/wireless/trace.h         | 19 +++++++++++++++++
+ 4 files changed, 101 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index fc01de19c7981a..2311d852e19ebc 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -10472,4 +10472,27 @@ cfg80211_s1g_get_primary_sibling(struct wiphy *wiphy,
+       return ieee80211_get_channel_khz(wiphy, sibling_1mhz_khz);
+ }
++
++/**
++ * cfg80211_incumbent_signal_notify - Notify userspace of incumbent signal detection
++ * @wiphy: the wiphy to use
++ * @chandef: channel definition in which the interference was detected
++ * @signal_interference_bitmap: bitmap indicating interference across 20 MHz segments
++ * @gfp: allocation context for message creation and multicast; pass GFP_ATOMIC
++ *    if called from atomic context (e.g. firmware event handler), otherwise
++ *    GFP_KERNEL
++ *
++ * Use this function to notify userspace when an incumbent signal is detected on
++ * the operating channel in the 6 GHz band. The notification includes the
++ * current channel definition and a bitmap representing interference across
++ * the operating bandwidth. Each bit in the bitmap corresponds to a 20 MHz
++ * segment, with the lowest bit representing the lowest frequency segment.
++ * Punctured sub-channels are included in the bitmap structure but are always
++ * set to zero since interference detection is not performed on them.
++ */
++void cfg80211_incumbent_signal_notify(struct wiphy *wiphy,
++                                    const struct cfg80211_chan_def *chandef,
++                                    u32 signal_interference_bitmap,
++                                    gfp_t gfp);
++
+ #endif /* __NET_CFG80211_H */
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index b63f718509060d..b53e2d78c7bb3f 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -1361,6 +1361,12 @@
+  *    user space that the NAN new cluster has been joined. The cluster ID is
+  *    indicated by %NL80211_ATTR_MAC.
+  *
++ * @NL80211_CMD_INCUMBENT_SIGNAL_DETECT: Once any incumbent signal is detected
++ *    on the operating channel in 6 GHz band, userspace is notified with the
++ *    signal interference bitmap using
++ *    %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
++ *    definition is also sent.
++ *
+  * @NL80211_CMD_MAX: highest used command number
+  * @__NL80211_CMD_AFTER_LAST: internal use
+  */
+@@ -1624,6 +1630,8 @@ enum nl80211_commands {
+       NL80211_CMD_NAN_NEXT_DW_NOTIFICATION,
+       NL80211_CMD_NAN_CLUSTER_JOINED,
++      NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
++
+       /* add new commands above here */
+       /* used to define NL80211_CMD_MAX below */
+@@ -2984,6 +2992,15 @@ enum nl80211_commands {
+  *    this feature during association. This is a flag attribute.
+  *    Currently only supported in mac80211 drivers.
+  *
++ * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying
++ *    the signal interference bitmap detected on the operating bandwidth for
++ *    %NL80211_CMD_INCUMBENT_SIGNAL_DETECT. Each bit represents a 20 MHz
++ *    segment, lowest bit corresponds to the lowest 20 MHz segment, in the
++ *    operating bandwidth where the interference is detected. Punctured
++ *    sub-channels are included in the bitmap structure; however, since
++ *    interference detection is not performed on these sub-channels, their
++ *    corresponding bits are consistently set to zero.
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3557,6 +3574,8 @@ enum nl80211_attrs {
+       NL80211_ATTR_UHR_CAPABILITY,
+       NL80211_ATTR_DISABLE_UHR,
++      NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
++
+       /* add attributes here, update the policy in nl80211.c */
+       __NL80211_ATTR_AFTER_LAST,
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index b94231c8441c48..d00357488ea8ea 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -21120,6 +21120,46 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
+ }
+ EXPORT_SYMBOL(cfg80211_ch_switch_notify);
++void cfg80211_incumbent_signal_notify(struct wiphy *wiphy,
++                                    const struct cfg80211_chan_def *chandef,
++                                    u32 signal_interference_bitmap,
++                                    gfp_t gfp)
++{
++      struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
++      struct sk_buff *msg;
++      void *hdr;
++
++      trace_cfg80211_incumbent_signal_notify(wiphy, chandef, signal_interference_bitmap);
++
++      msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
++      if (!msg)
++              return;
++
++      hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_INCUMBENT_SIGNAL_DETECT);
++      if (!hdr)
++              goto nla_put_failure;
++
++      if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
++              goto nla_put_failure;
++
++      if (nl80211_send_chandef(msg, chandef))
++              goto nla_put_failure;
++
++      if (nla_put_u32(msg, NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
++                      signal_interference_bitmap))
++              goto nla_put_failure;
++
++      genlmsg_end(msg, hdr);
++
++      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
++                              NL80211_MCGRP_MLME, gfp);
++      return;
++
++nla_put_failure:
++      nlmsg_free(msg);
++}
++EXPORT_SYMBOL(cfg80211_incumbent_signal_notify);
++
+ void cfg80211_ch_switch_started_notify(struct net_device *dev,
+                                      struct cfg80211_chan_def *chandef,
+                                      unsigned int link_id, u8 count,
+diff --git a/net/wireless/trace.h b/net/wireless/trace.h
+index 643ccf4f022722..352a57d8b96819 100644
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -4225,6 +4225,25 @@ TRACE_EVENT(cfg80211_nan_cluster_joined,
+                 WDEV_PR_ARG, __entry->cluster_id,
+                 __entry->new_cluster ? " [new]" : "")
+ );
++
++TRACE_EVENT(cfg80211_incumbent_signal_notify,
++      TP_PROTO(struct wiphy *wiphy,
++               const struct cfg80211_chan_def *chandef,
++               u32 signal_interference_bitmap),
++      TP_ARGS(wiphy, chandef, signal_interference_bitmap),
++      TP_STRUCT__entry(
++              WIPHY_ENTRY
++              CHAN_DEF_ENTRY
++              __field(u32, signal_interference_bitmap)
++      ),
++      TP_fast_assign(
++              WIPHY_ASSIGN;
++              CHAN_DEF_ASSIGN(chandef);
++              __entry->signal_interference_bitmap = signal_interference_bitmap;
++      ),
++      TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", signal_interference_bitmap=0x%x",
++                WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->signal_interference_bitmap)
++);
+ #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
+ #undef TRACE_INCLUDE_PATH
+-- 
+2.53.0
+
diff --git a/queue-7.0/wifi-cfg80211-enforce-he-eht-cap-oper-consistency.patch b/queue-7.0/wifi-cfg80211-enforce-he-eht-cap-oper-consistency.patch
new file mode 100644 (file)
index 0000000..ba57576
--- /dev/null
@@ -0,0 +1,42 @@
+From 9409bb870ab551164c0635f3f918a550680dbd66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 11:18:11 +0200
+Subject: wifi: cfg80211: enforce HE/EHT cap/oper consistency
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit cb9959ab5f99611d27a06586add84811fe8102dc ]
+
+Xiang Mei reports that mac80211 could crash if eht_cap is set
+but eht_oper isn't. Rather than fixing that for the individual
+user(s), enforce that both HE/EHT have consistent elements.
+
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Fixes: 22c64f37e1d4 ("wifi: mac80211: Update MCS15 support in link_conf")
+Link: https://patch.msgid.link/20260603091812.101894-2-johannes@sipsolutions.net
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 84fcfb1e53a156..fe0c0c198b2526 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -6499,6 +6499,12 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
+                       return -EINVAL;
+       }
++      if (!!params->he_cap != !!params->he_oper)
++              return -EINVAL;
++
++      if (!!params->eht_cap != !!params->eht_oper)
++              return -EINVAL;
++
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-7.0/wifi-fix-leak-if-split-6-ghz-scanning-fails.patch b/queue-7.0/wifi-fix-leak-if-split-6-ghz-scanning-fails.patch
new file mode 100644 (file)
index 0000000..34a9a77
--- /dev/null
@@ -0,0 +1,79 @@
+From d609b22094b527fb93ea062425ed0e11af546306 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:41:56 +0300
+Subject: wifi: fix leak if split 6 GHz scanning fails
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+[ Upstream commit e8694f7cc29287e843648d1075177b9a2000d957 ]
+
+rdev->int_scan_req is leaked if cfg80211_scan() fails.  Note that it's
+supposed to be released at ___cfg80211_scan_done() but this doesn't happen
+as rdev->scan_req is NULL at that point, too, leading to the early return
+from the freeing function.
+
+unreferenced object 0xffff8881161d0800 (size 512):
+  comm "wpa_supplicant", pid 379, jiffies 4294749765
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+    00 00 00 00 00 00 00 00 f0 81 13 16 81 88 ff ff  ................
+  backtrace (crc c867fdb6):
+    kmemleak_alloc+0x89/0x90
+    __kmalloc_noprof+0x2fd/0x410
+    cfg80211_scan+0x133/0x730
+    nl80211_trigger_scan+0xc69/0x1cc0
+    genl_family_rcv_msg_doit+0x204/0x2f0
+    genl_rcv_msg+0x431/0x6b0
+    netlink_rcv_skb+0x143/0x3f0
+    genl_rcv+0x27/0x40
+    netlink_unicast+0x4f6/0x820
+    netlink_sendmsg+0x797/0xce0
+    __sock_sendmsg+0xc4/0x160
+    ____sys_sendmsg+0x5e4/0x890
+    ___sys_sendmsg+0xf8/0x180
+    __sys_sendmsg+0x136/0x1e0
+    __x64_sys_sendmsg+0x76/0xc0
+    x64_sys_call+0x13f0/0x17d0
+
+Found by Linux Verification Center (linuxtesting.org).
+
+Fixes: c8cb5b854b40 ("nl80211/cfg80211: support 6 GHz scanning")
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Link: https://patch.msgid.link/20260601094157.92703-1-pchelkin@ispras.ru
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/scan.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/net/wireless/scan.c b/net/wireless/scan.c
+index 358cbc9e43d851..27a56ee2e8f0b3 100644
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -1071,6 +1071,7 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)
+       struct cfg80211_scan_request_int *request;
+       struct cfg80211_scan_request_int *rdev_req = rdev->scan_req;
+       u32 n_channels = 0, idx, i;
++      int err;
+       if (!(rdev->wiphy.flags & WIPHY_FLAG_SPLIT_SCAN_6GHZ)) {
+               rdev_req->req.first_part = true;
+@@ -1100,8 +1101,14 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)
+       rdev_req->req.scan_6ghz = false;
+       rdev_req->req.first_part = true;
++      err = rdev_scan(rdev, request);
++      if (err) {
++              kfree(request);
++              return err;
++      }
++
+       rdev->int_scan_req = request;
+-      return rdev_scan(rdev, request);
++      return 0;
+ }
+ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
+-- 
+2.53.0
+
diff --git a/queue-7.0/wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch b/queue-7.0/wifi-iwlwifi-mvm-don-t-support-the-reset-handshake-f.patch
new file mode 100644 (file)
index 0000000..95fde8b
--- /dev/null
@@ -0,0 +1,45 @@
+From 3f686e202dae6cd32d719813370e85457b08028e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 08:57:05 +0300
+Subject: wifi: iwlwifi: mvm: don't support the reset handshake for old
+ firmwares
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+[ Upstream commit 0eaa1f245ac03ed0c6394159360532726f666811 ]
+
+-77.ucode doesn't contain the fixes for this flow it seems.
+Don't use the firmware reset handshake even if the firmware claims
+support for it.
+
+Fixes: 906d4eb84408 ("iwlwifi: support firmware reset handshake")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220600
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Reviewed-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20260529085453.9307b81d9b02.I21bba9e649f4cd0e35d3ea6cd97a03258be5832f@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+index ae177477b20127..384bed95835d74 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+@@ -1416,6 +1416,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
+               fw_has_capa(&mvm->fw->ucode_capa,
+                           IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);
++      /* Those firmware versions claim to support the fw_reset_handshake
++       * but they are buggy.
++       */
++      if (IWL_UCODE_MAJOR(mvm->fw->ucode_ver) <= 77)
++              trans->conf.fw_reset_handshake = false;
++
+       trans->conf.queue_alloc_cmd_ver =
+               iwl_fw_lookup_cmd_ver(mvm->fw,
+                                     WIDE_ID(DATA_PATH_GROUP,
+-- 
+2.53.0
+
diff --git a/queue-7.0/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch b/queue-7.0/wifi-mac80211-limit-injected-antenna-index-in-ieee80.patch
new file mode 100644 (file)
index 0000000..a70e9b4
--- /dev/null
@@ -0,0 +1,61 @@
+From f4aa7232dac3a99d8f9a07db633511e8b3aa2c43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 06:47:21 +0530
+Subject: wifi: mac80211: limit injected antenna index in
+ ieee80211_parse_tx_radiotap
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 6c0cf89f36ac0c0fd8687a4ccdce2efb23a9c663 ]
+
+When parsing the radiotap header of an injected frame,
+ieee80211_parse_tx_radiotap() uses the IEEE80211_RADIOTAP_ANTENNA value
+directly as a shift count:
+
+       info->control.antennas |= BIT(*iterator.this_arg);
+
+*iterator.this_arg is an 8-bit value taken straight from the frame
+supplied by userspace, so BIT() can be asked to shift by up to 255. That
+is undefined behaviour on the unsigned long and is reported by UBSAN:
+
+  UBSAN: shift-out-of-bounds in net/mac80211/tx.c:2174:30
+  shift exponent 235 is too large for 64-bit type 'unsigned long'
+  Call Trace:
+   ieee80211_parse_tx_radiotap+0xadb/0x1950 net/mac80211/tx.c:2174
+   ieee80211_monitor_start_xmit+0xb1f/0x1250 net/mac80211/tx.c:2451
+   ...
+   packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3109
+
+info->control.antennas is a 2-bit bitmap (u8 antennas:2), so only antenna
+indices 0 and 1 can ever be represented. Ignore any larger value instead
+of shifting out of bounds.
+
+Reported-by: syzbot+8e0622f6d9446420271f@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8e0622f6d9446420271f
+Fixes: ef246a1480cc ("wifi: mac80211: support antenna control in injection")
+Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
+Link: https://patch.msgid.link/20260531011721.102941-1-kartikey406@gmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/tx.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index b7aedaab848386..d2ba2d81224f97 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -2172,7 +2172,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
+               case IEEE80211_RADIOTAP_ANTENNA:
+                       /* this can appear multiple times, keep a bitmap */
+-                      info->control.antennas |= BIT(*iterator.this_arg);
++                      /* control.antennas is only a 2-bit bitmap */
++                      if (*iterator.this_arg < 2)
++                              info->control.antennas |= BIT(*iterator.this_arg);
+                       break;
+               case IEEE80211_RADIOTAP_DATA_RETRIES:
+-- 
+2.53.0
+
diff --git a/queue-7.0/wifi-nl80211-split-out-uhr-operation-information.patch b/queue-7.0/wifi-nl80211-split-out-uhr-operation-information.patch
new file mode 100644 (file)
index 0000000..23af1f7
--- /dev/null
@@ -0,0 +1,108 @@
+From f34fec4b61e89d87bca7e681572d9547360071e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Mar 2026 22:17:09 +0100
+Subject: wifi: nl80211: split out UHR operation information
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit e4b993f2bca78357b430170574f8de7bc7874088 ]
+
+The beacon doesn't contain the full UHR operation, a number
+of fields (such as NPCA) are only partially there. Add a new
+attribute to contain the full information, so it's available
+to the driver/mac80211.
+
+Link: https://patch.msgid.link/20260303221710.866bacf82639.Iafdf37fb0f4304bdcdb824977d61e17b38c47685@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Stable-dep-of: cb9959ab5f99 ("wifi: cfg80211: enforce HE/EHT cap/oper consistency")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/nl80211.h |  6 ++++++
+ net/wireless/nl80211.c       | 26 ++++++++++++++++----------
+ 2 files changed, 22 insertions(+), 10 deletions(-)
+
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index b53e2d78c7bb3f..b997e6c6fc4b38 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -3001,6 +3001,10 @@ enum nl80211_commands {
+  *    interference detection is not performed on these sub-channels, their
+  *    corresponding bits are consistently set to zero.
+  *
++ * @NL80211_ATTR_UHR_OPERATION: Full UHR Operation element, as it appears in
++ *    association response etc., since it's abridged in the beacon. Used
++ *    for START_AP etc.
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3576,6 +3580,8 @@ enum nl80211_attrs {
+       NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
++      NL80211_ATTR_UHR_OPERATION,
++
+       /* add attributes here, update the policy in nl80211.c */
+       __NL80211_ATTR_AFTER_LAST,
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index d00357488ea8ea..84fcfb1e53a156 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -341,6 +341,17 @@ static int validate_uhr_capa(const struct nlattr *attr,
+       return ieee80211_uhr_capa_size_ok(data, len, false);
+ }
++static int validate_uhr_operation(const struct nlattr *attr,
++                                struct netlink_ext_ack *extack)
++{
++      const u8 *data = nla_data(attr);
++      unsigned int len = nla_len(attr);
++
++      if (!ieee80211_uhr_oper_size_ok(data, len, false))
++              return -EINVAL;
++      return 0;
++}
++
+ /* policy for the attributes */
+ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
+@@ -946,6 +957,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
+       [NL80211_ATTR_UHR_CAPABILITY] =
+               NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_capa, 255),
+       [NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG },
++      [NL80211_ATTR_UHR_OPERATION] =
++              NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_operation),
+ };
+ /* policy for the key attributes */
+@@ -6486,16 +6499,6 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
+                       return -EINVAL;
+       }
+-      cap = cfg80211_find_ext_elem(WLAN_EID_EXT_UHR_OPER, ies, ies_len);
+-      if (cap) {
+-              if (!cap->datalen)
+-                      return -EINVAL;
+-              params->uhr_oper = (void *)(cap->data + 1);
+-              if (!ieee80211_uhr_oper_size_ok((const u8 *)params->uhr_oper,
+-                                              cap->datalen - 1, true))
+-                      return -EINVAL;
+-      }
+-
+       return 0;
+ }
+@@ -6928,6 +6931,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
+       if (err)
+               goto out;
++      if (info->attrs[NL80211_ATTR_UHR_OPERATION])
++              params->uhr_oper = nla_data(info->attrs[NL80211_ATTR_UHR_OPERATION]);
++
+       err = nl80211_validate_ap_phy_operation(params);
+       if (err)
+               goto out;
+-- 
+2.53.0
+
diff --git a/queue-7.0/xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch b/queue-7.0/xsk-cache-csum_start-csum_offset-to-fix-toctou-in-xs.patch
new file mode 100644 (file)
index 0000000..94e0b4e
--- /dev/null
@@ -0,0 +1,73 @@
+From 122e19483ae12798b6f95014817fec16b2a38bde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 May 2026 12:26:30 +0800
+Subject: xsk: cache csum_start/csum_offset to fix TOCTOU in xsk_skb_metadata()
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 22ba97ea9cc1f63a0d0244fae38057ed452b6ac7 ]
+
+The TX metadata area resides in the UMEM buffer which is memory-mapped
+and concurrently writable by userspace. In xsk_skb_metadata(),
+csum_start and csum_offset are read from shared memory for bounds
+validation, then read again for skb assignment. A malicious userspace
+application can race to overwrite these values between the two reads,
+bypassing the bounds check and causing out-of-bounds memory access
+during checksum computation in the transmit path.
+
+Fix this by reading csum_start and csum_offset into local variables
+once, then using the local copies for both validation and assignment.
+
+Note that other metadata fields (flags, launch_time) and the cached
+csum fields may be mutually inconsistent due to concurrent userspace
+writes, but this is benign: the only security-critical invariant is
+that each field's validated value is the same one used, which local
+caching guarantees.
+
+Closes: https://lore.kernel.org/all/20260503200927.73EA1C2BCB4@smtp.kernel.org/
+Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Fixes: 48eb03dd2630 ("xsk: Add TX timestamp and TX checksum offload support")
+Link: https://patch.msgid.link/20260530042630.80626-1-kerneljasonxing@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xsk.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index c8ef9e427c9cd5..db0fb2203af63c 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -683,6 +683,7 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+                           u32 hr)
+ {
+       struct xsk_tx_metadata *meta = NULL;
++      u16 csum_start, csum_offset;
+       if (unlikely(pool->tx_metadata_len == 0))
+               return -EINVAL;
+@@ -692,13 +693,15 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
+               return -EINVAL;
+       if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) {
+-              if (unlikely(meta->request.csum_start +
+-                           meta->request.csum_offset +
++              csum_start = READ_ONCE(meta->request.csum_start);
++              csum_offset = READ_ONCE(meta->request.csum_offset);
++
++              if (unlikely(csum_start + csum_offset +
+                            sizeof(__sum16) > desc->len))
+                       return -EINVAL;
+-              skb->csum_start = hr + meta->request.csum_start;
+-              skb->csum_offset = meta->request.csum_offset;
++              skb->csum_start = hr + csum_start;
++              skb->csum_offset = csum_offset;
+               skb->ip_summed = CHECKSUM_PARTIAL;
+               if (unlikely(pool->tx_sw_csum)) {
+-- 
+2.53.0
+