summaryrefslogtreecommitdiff
path: root/net/ipv6
AgeCommit message (Collapse)Author
9 daysipv6: fib6: fix NULL deref in fib6_walk_continue() on multi-batch dumpPengfei Zhang
inet6_dump_fib() saves its progress in cb->args[1] as a positional index within the current hash chain. Between batches, a concurrent fib6_new_table() can insert a new table at the chain head, shifting all existing entries. The saved index then lands on a different table, causing fib6_dump_table() to set w->root to the wrong table while w->node still points into the previous one. fib6_walk_continue() dereferences w->node->parent (NULL) and panics: BUG: kernel NULL pointer dereference, address: 0000000000000008 RIP: 0010:fib6_walk_continue+0x6e/0x170 Call Trace: <TASK> fib6_dump_table.isra.0+0xc5/0x240 inet6_dump_fib+0xf6/0x420 rtnl_dumpit+0x30/0xa0 netlink_dump+0x15b/0x460 netlink_recvmsg+0x1d6/0x2a0 ____sys_recvmsg+0x17a/0x190 Fix by storing tb->tb6_id in cb->args[1] instead of a positional index. On resume, skip entries until the id matches; a concurrent head-insert can never match the saved id, so the walker always resumes on the correct table. Fixes: 1b43af5480c3 ("[IPV6]: Increase number of possible routing tables to 2^32") Signed-off-by: Pengfei Zhang <zhangfeionline@gmail.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260625070517.965597-1-zhangfeionline@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
12 daysseg6: validate SRH length before reading fixed fieldsNuoqi Gui
seg6_validate_srh() reads fixed SRH fields such as srh->type and srh->hdrlen before checking that the supplied length covers the fixed struct ipv6_sr_hdr fields. The BPF SEG6 encap path reaches this with a BPF program-supplied pointer and length: bpf_lwt_push_encap() and the SEG6 local BPF END_B6 and END_B6_ENCAP actions call bpf_push_seg6_encap(), which forwards the length to seg6_validate_srh() with no minimum-size guard. A 2-byte SEG6 encap header can therefore make the validator read srh->type at offset 2 beyond the caller-supplied buffer. Reject lengths shorter than the fixed SRH at the top of seg6_validate_srh(), before any field is read. This fixes the BPF helper path and keeps the common validator robust. Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers") Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn> Reviewed-by: Andrea Mayer <andrea.mayer@uniroma2.it> Link: https://patch.msgid.link/20260623-f01-17-seg6-srh-len-v2-1-2edc40e9e3e1@mails.tsinghua.edu.cn Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23ipv6: fix missing notification for ignore_routes_with_linkdownFernando Fernandez Mancera
When changing the ignore_routes_with_linkdown sysctl for a specific interface, the RTM_NEWNETCONF netlink notification was not being emitted to userspace. Fix this by emitting the notification when needed. In addition, fix bogus return value for successful "all" and specific interface write operation leading to a wrong reset of the position pointer. Fixes: 35103d11173b ("net: ipv6 sysctl option to ignore routes when nexthop link is down") Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260622130857.5115-7-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23ipv6: fix state corruption during proxy_ndp sysctl restartFernando Fernandez Mancera
When handling proxy_ndp, if rtnl_net_trylock() fails, the operation is retried but as the value was already modified by the initial proc_dointvec() call, the restarted syscall will read the newly modified value as the 'old' state. Fix this by taking the RTNL lock before parsing the input value if the operation is a write. Fixes: c92d5491a6d9 ("netconf: add support for IPv6 proxy_ndp") Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260622130857.5115-6-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23ipv6: fix error handling in disable_policy sysctlFernando Fernandez Mancera
When writing to the disable_policy sysctl, if proc_dointvec() fails to parse the input, it returns a negative error code. The current implementation is resetting the position argument even if an error occurred during proc_dointvec() and not only during sysctl restart. Fix this by checking the return value of proc_dointvec() and returning early on failure. Fixes: df789fe75206 ("ipv6: Provide ipv6 version of "disable_policy" sysctl") Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260622130857.5115-5-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23ipv6: fix error handling in forwarding sysctlFernando Fernandez Mancera
When writing to the forwarding sysctl, if proc_dointvec() fails to parse the input, it returns a negative error code. The current implementation is overwriting that error for write operations. This results in a silent failure, it returns a successful write although the configuration was not modified at all. When modifying the "all" variant it can also modify the configuration of existing interfaces to the wrong value. Fix this by checking the return value of proc_dointvec() and returning early on failure. In addition, adjust return code of addrconf_fixup_forwarding() for successful operation. Fixes: b325fddb7f86 ("ipv6: Fix sysctl unregistration deadlock") Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260622130857.5115-4-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23ipv6: fix error handling in ignore_routes_with_linkdown sysctlFernando Fernandez Mancera
When writing to the ignore_routes_with_linkdown sysctl, if proc_dointvec() fails to parse the input, it returns a negative error code. The current implementation is overwriting that error for write operations. This results in a silent failure, it returns a successful write although the configuration was not modified at all. When modifying the "all" variant it can also modify the configuration of existing interfaces to the wrong value. Fix this by checking the return value of proc_dointvec() and returning early on failure. Fixes: 35103d11173b ("net: ipv6 sysctl option to ignore routes when nexthop link is down") Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260622130857.5115-3-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23ipv6: fix error handling in disable_ipv6 sysctlFernando Fernandez Mancera
When writing to the disable_ipv6 sysctl, if proc_dointvec() fails to parse the input, it returns a negative error code. The current implementation is overwriting that error for write operations. This results in a silent failure, it returns a successful write although the configuration was not modified at all. When modifying the "all" variant it can also modify the configuration of existing interfaces to the wrong value. Fix this by checking the return value of proc_dointvec() and returning early on failure. Fixes: 56d417b12e57 ("IPv6: Add 'autoconf' and 'disable_ipv6' module parameters") Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260622130857.5115-2-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-23Merge tag 'ipsec-2026-06-22' of ↵Jakub Kicinski
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec Steffen Klassert says: ==================== pull request (net): ipsec 2026-06-22 1) xfrm: use compat translator only for u64 alignment mismatch Gate the XFRM_USER_COMPAT translator on COMPAT_FOR_U64_ALIGNMENT so 32-bit compat tasks on arches whose 32-bit ABI already matches the native 64-bit layout are no longer rejected with -EOPNOTSUPP. From Sanman Pradhan. 2) net: af_key: initialize alg_key_len for IPComp states Initialize the alg_key_len to 0 in the IPComp branch of pfkey_msg2xfrm_state() so an uninitialized value cannot drive xfrm_alg_len() into a slab-out-of-bounds kmemdup during XFRM_MSG_MIGRATE. From Zijing Yin. 3) xfrm: Fix dev use-after-free in xfrm async resumption Stash the original skb->dev and extend the RCU critical section across xfrm_rcv_cb() and transport_finish() to prevent a tunnel-device UAF and original-device refcount leak when a callback replaces skb->dev. From Dong Chenchen. 4) xfrm: Fix xfrm state cache insertion race Move the state-validity check inside xfrm_state_lock in the input state cache insertion path so a state cannot be killed between the check and the insert. From Herbert Xu. 5) xfrm: annotate data-races around xfrm_policy_count[] and xfrm_policy_default[] Add READ_ONCE()/WRITE_ONCE() annotations on xfrm_policy_count and xfrm_policy_default to silence the KCSAN data race reported on net->xfrm.policy_count. From Eric Dumazet. 6) espintcp: use sk_msg_free_partial to fix partial send Replace the manual skmsg accounting in espintcp with sk_msg_free_partial() so the skmsg stays consistent on every iteration and the partial-send accounting bugs go away. From Sabrina Dubroca. 7) xfrm: validate selector family and prefixlen during match Reject mismatched address families in xfrm_selector_match() and bound prefixlen in addr4_match()/addr_match() to prevent the shift-out-of-bounds syzbot reported when an AF_UNSPEC selector with a large prefixlen is matched against an IPv4 flow. From Eric Dumazet. * tag 'ipsec-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: validate selector family and prefixlen during match espintcp: use sk_msg_free_partial to fix partial send xfrm: annotate data-races around xfrm_policy_count[] and xfrm_policy_default[] xfrm: Fix xfrm state cache insertion race xfrm: Fix dev use-after-free in xfrm async resumption net: af_key: initialize alg_key_len for IPComp states xfrm: use compat translator only for u64 alignment mismatch ==================== Link: https://patch.msgid.link/20260622075726.29685-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-22ipv6: Fix null-ptr-deref in fib6_nh_mtu_change().Xiang Mei
fib6_nh_mtu_change() re-fetches idev via __in6_dev_get(arg->dev) and dereferences idev->cnf.mtu6 without a NULL check. addrconf_ifdown() clears dev->ip6_ptr with RCU_INIT_POINTER() after rt6_disable_ip() has released tb6_lock, so the RA-driven MTU walk can observe a NULL idev and oops. The caller rt6_mtu_change_route() guards its own __in6_dev_get(), but this re-fetch is unguarded; nexthop-backed routes survive addrconf_ifdown()'s flush, so the walk still reaches it after ip6_ptr is nulled. Return 0 when idev is NULL, matching rt6_mtu_change_route() and the fib6_mtu() fix in commit 5ad509c1fdad ("ipv6: Fix null-ptr-deref in fib6_mtu()."). Oops: general protection fault, ... KASAN: null-ptr-deref in range [0x00000000000002a8-0x00000000000002af] RIP: 0010:fib6_nh_mtu_change+0x203/0x990 rt6_mtu_change_route+0x141/0x1d0 __fib6_clean_all+0xd0/0x160 rt6_mtu_change+0xb4/0x100 ndisc_router_discovery+0x24b5/0x2cb0 icmpv6_rcv+0x12e9/0x1710 ipv6_rcv+0x39b/0x410 Fixes: c0b220cf7d80 ("ipv6: Refactor exception functions") Reported-by: Weiming Shi <bestswngs@gmail.com> Signed-off-by: Xiang Mei <xmei5@asu.edu> Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260619045334.2427073-1-xmei5@asu.edu Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-22Merge tag 'nf-26-06-21' of ↵Jakub Kicinski
git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net. This batches fixes for real crashes with trivial/correctness fixes. There is too a rework of the conntrack expectation timeout strategy to deal with a possible race when removing an expectation. 1) Fix the incorrect flowtable timeout extension for entries in hw offload, from Adrian Bente. This is correcting a defect in the functionality, no crash. 2) Hold reference to device under the fake dst in br_netfilter, from Haoze Xie. This is fixing a possible UaF if the device is removed while packet is sitting in nfqueue. 3) Reject template conntrack in xt_cluster, otherwise access to uninitialize conntrack fields are possible leading to WARN_ON due to unset layer 3 protocol. From Wyatt Feng. 4) Make sure the IPv6 tunnel header is in the linear skb data area before pulling. While at it remove incomplete NEXTHDR_DEST support. From Lorenzo Bianconi. This possibly leading to crash if IPv4 header is not in the linear area. 5) Use test_bit_acquire in ipset hash set to avoid reordering of subsequent memory access. This is addressing a LLM related report, no crash has been observed. From Jozsef Kadlecsik. 6) Use test_bit_acquire in ipset bitmap set too, for the same reason as in the previous patch, from Jozsef Kadlecsik. 7) Call kfree_rcu() after rcu_assign_pointer() to address a possible UaF if kfree_rcu() runs inmediately, which to my understanding never happens. Never observed in practise, reported by LLM. Also from Jozsef Kadlecsik. 8) Use disable_delayed_work_sync() instead cancel_delayed_work_sync() to avoid that ipset GC handler re-queues work as reported by LLM. From Jozsef Kadlecsik. This is for correctness. 9) Restore the check in nft_payload for exceeding payloda offset over 2^16. From Florian Westphal. This fixes a silent truncation, not a big deal, but better be assertive and reject it. 10) Validate NFT_META_BRI_IIFHWADDR can only run from bridge prerouting. From Florian Westphal. Harmless but it could allow to read bytes from skb->cb. 11) Zero out destination hardware address during the flowtable path setup, also from Florian. This is a correctness fix, LLM points that possible infoleak can happen but topology to achieve it is not clear. 12) Skip IPv4 options if present when building the IPV4 reject reply. Otherwise bytes in the IPv4 options header can be sent back to origin where the ICMP header is being expected. Again from Florian Westphal. 13) Replace timer API for expectation by GC worker approach. This is implicitly fixing a race between nf_ct_remove_expectations() which might fail to remove the expectation due to timer_del() returning false because timer has expired and callback is being run concurrently. This fix is addressing a crash that has been already reported with a reproducer. 14) Check if br_vlan_get_pvid_rcu() fails, otherwise possible stack infoleak of 4-bytes. From Florian Westphal. * tag 'nf-26-06-21' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nft_meta_bridge: fix NFT_META_BRI_IIFPVID stack leak netfilter: nf_conntrack_expect: use conntrack GC to reap expectations netfilter: nf_reject: skip iphdr options when looking for icmp header netfilter: nft_flow_offload: zero device address for non-ether case netfilter: nft_meta_bridge: add validate callback for get operations netfilter: nft_payload: reject offsets exceeding 65535 bytes netfilter: ipset: make sure gc is properly stopped netfilter: ipset: fix order of kfree_rcu() and rcu_assign_pointer() netfilter: ipset: Don't use test_bit() in lockless RCU readers in bitmap types netfilter: ipset: Don't use test_bit() in lockless RCU readers in hash types netfilter: flowtable: fix and simplify IP6IP6 tunnel handling netfilter: xt_cluster: reject template conntracks in hash match netfilter: nf_queue: pin bridge device while NFQUEUE holds fake dst netfilter: flowtable: fix offloaded ct timeout never being extended ==================== Link: https://patch.msgid.link/20260620222738.112506-1-pablo@netfilter.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-21ipv6: ioam: fix type confusion of dst_entryJiayuan Chen
IOAM uses a dummy dst_entry(null_dst) to mark that the destination should not be changed after the transformation. This dst is stored in the IOAM lwt state and may be passed to dst_cache_set_ip6(). However, the IPv6 dst cache path eventually calls rt6_get_cookie(), which treats the dst_entry as part of a struct rt6_info. Since the null_dst was embedded directly as a struct dst_entry in struct ioam6_lwt, this resulted in an invalid cast and rt6_get_cookie() reading fields from the wrong object. In practice, the wrong cookie is not used while dst->obsolete is zero, but rt6_get_cookie() may also access per-cpu value when rt->sernum is zero. In this case, rt->sernum aliases ioam6_lwt::cache::reset_ts, which can become zero, making this a potential invalid pointer access. Fix this by embedding a full struct rt6_info for the dummy IPv6 route and passing its dst member to the dst APIs. Fixes: 47ce7c854563 ("net: ipv6: ioam6: fix double reallocation") Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev> Reviewed-by: Justin Iurman <justin.iurman@gmail.com> Link: https://patch.msgid.link/20260618104336.48934-1-jiayuan.chen@linux.dev Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-21ipv6: account for fraggap on the paged allocation pathWongi Lee
In __ip6_append_data(), when the paged-allocation branch is taken (MSG_MORE / NETIF_F_SG / large fraglen), alloclen and pagedlen are computed as alloclen = fragheaderlen + transhdrlen; pagedlen = datalen - transhdrlen; datalen already includes fraggap (datalen = length + fraggap). When fraggap is non-zero, this is not the first skb and transhdrlen is zero. The fraggap bytes carried over from the previous skb are copied just past the fragment headers in the new skb's linear area. The linear area is therefore undersized by fraggap bytes while pagedlen is overstated by the same amount, and the copy writes past skb->end into the trailing skb_shared_info. An unprivileged user can trigger this via a UDPv6 socket using MSG_MORE together with MSG_SPLICE_PAGES. The bad accounting was introduced by commit 773ba4fe9104 ("ipv6: avoid partial copy for zc"). Before commit ce650a166335 ("udp6: Fix __ip6_append_data()'s handling of MSG_SPLICE_PAGES"), the negative copy value caused -EINVAL to be returned. That later commit allowed MSG_SPLICE_PAGES to proceed in this case, making the corruption triggerable. The non-paged branch sets alloclen to fraglen, which already accounts for fraggap because datalen does. Bring the paged branch in line by adding fraggap to alloclen and subtracting it from pagedlen. After this adjustment, copy no longer collapses to -fraggap on the paged path, so remove the stale comment describing that old arithmetic. Since a negative copy is no longer expected for a valid MSG_SPLICE_PAGES case, remove the MSG_SPLICE_PAGES exception from the negative copy check. Fixes: 773ba4fe9104 ("ipv6: avoid partial copy for zc") Signed-off-by: Jungwoo Lee <jwlee2217@gmail.com> Signed-off-by: Wongi Lee <qw3rtyp0@gmail.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/ajFTqRljatR17fFy@DESKTOP-19IMU7U.localdomain Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-21ipv6: ndisc: fix NULL deref in accept_untracked_na()Weiming Shi
accept_untracked_na() re-fetches the inet6_dev with __in6_dev_get(dev) and dereferences idev->cnf.accept_untracked_na without a NULL check, even though its only caller ndisc_recv_na() already fetched and NULL-checked idev for the same device. Both reads of dev->ip6_ptr run in the same RCU read-side critical section, but a concurrent addrconf_ifdown() can clear dev->ip6_ptr between them: lowering the MTU below IPV6_MIN_MTU calls addrconf_ifdown() without the synchronize_net() that orders the unregister path, so the re-fetch returns NULL and oopses: BUG: KASAN: null-ptr-deref in ndisc_recv_na (net/ipv6/ndisc.c:974) Read of size 4 at addr 0000000000000364 Call Trace: <IRQ> ndisc_recv_na (net/ipv6/ndisc.c:974) icmpv6_rcv (net/ipv6/icmp.c:1193) ip6_protocol_deliver_rcu (net/ipv6/ip6_input.c:479) ip6_input_finish (net/ipv6/ip6_input.c:534) ip6_input (net/ipv6/ip6_input.c:545) ip6_mc_input (net/ipv6/ip6_input.c:635) ipv6_rcv (net/ipv6/ip6_input.c:351) </IRQ> It is reachable by an unprivileged user via a network namespace. Pass the caller's already validated idev instead of re-fetching it; the idev stays alive for the whole RCU critical section, so it is safe even after dev->ip6_ptr has been cleared. Fixes: aaa5f515b16b ("net: ipv6: new accept_untracked_na option to accept na only if in-network") Reported-by: Xiang Mei <xmei5@asu.edu> Signed-off-by: Weiming Shi <bestswngs@gmail.com> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Link: https://patch.msgid.link/20260617065512.2529757-2-bestswngs@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-21net: sit: require CAP_NET_ADMIN in the device netns for changelinkMaoyi Xie
ipip6_changelink() operates on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net. Gate ipip6_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed. sit was the one tunnel type not covered by the recent series that added this check to the other changelink() handlers. Fixes: 5e6700b3bf98 ("sit: add support of x-netns") Link: https://lore.kernel.org/netdev/20260612085941.3158249-1-maoyixie.tju@gmail.com/ Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com> Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260618070817.3378283-1-maoyixie.tju@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-19netfilter: flowtable: fix and simplify IP6IP6 tunnel handlingLorenzo Bianconi
Fix nf_flow_ip6_tunnel_proto() to use pskb_may_pull() instead of skb_header_pointer() to ensure the outer IPv6 header is in the skb headroom, which is required for subsequent packet processing. Move ctx->offset update inside the IPPROTO_IPV6 conditional block since it should only be adjusted when an IP6IP6 tunnel is actually detected. Simplify the rx path by removing ipv6_skip_exthdr() and checking ip6h->nexthdr directly, as the flowtable fast path only handles simple IP6IP6 encapsulation without extension headers. Drop the tunnel encapsulation limit destination option support from the tx path to match, since the rx path no longer handles extension headers. Remove the encap_limit parameter from nf_flow_offload_ipv6_forward(), nf_flow_tunnel_ip6ip6_push() and nf_flow_tunnel_v6_push(), along with the ipv6_tel_txoption struct and related headroom/MTU adjustments. Fixes: d98103575dcdd ("netfilter: flowtable: Add IP6IP6 rx sw acceleration") Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2026-06-17net: ip6_vti: require CAP_NET_ADMIN in the device netns for changelinkMaoyi Xie
vti6_changelink() operates on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net. Gate vti6_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed. Reported-by: Xiao Liang <shaw.leon@gmail.com> Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/ Fixes: 61220ab34948 ("vti6: Enable namespace changing") Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260612085941.3158249-7-maoyixie.tju@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-17net: ip6_gre: require CAP_NET_ADMIN in the device netns for changelinkMaoyi Xie
ip6gre_changelink() and ip6erspan_changelink() operate on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net. Gate both ops on rtnl_dev_link_net_capable() at their top, before any attribute is parsed. Reported-by: Xiao Liang <shaw.leon@gmail.com> Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/ Fixes: 690afc165bb3 ("net: ip6_gre: fix moving ip6gre between namespaces") Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260612085941.3158249-6-maoyixie.tju@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-17net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelinkMaoyi Xie
ip6_tnl_changelink() operates on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net. Gate ip6_tnl_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed. Reported-by: Xiao Liang <shaw.leon@gmail.com> Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/ Fixes: 0bd8762824e7 ("ip6tnl: add x-netns support") Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260612085941.3158249-5-maoyixie.tju@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-16Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netJakub Kicinski
Merge in late fixes in preparation for the net-next PR. Conflicts: net/tls/tls_sw.c 406e8a651a7b ("net: skmsg: preserve sg.copy across SG transforms") 79511603a65b ("tls: remove dead sockmap (psock) handling from the SW path") drivers/net/ethernet/microsoft/mana/mana_en.c f8fd56977eeea ("net: mana: guard TX wq object destroy with INVALID_MANA_HANDLE check") d07efe5a6e641 ("net: mana: Use per-queue allocation for tx_qp to reduce allocation size") https://lore.kernel.org/ajAPXu-C_PuTgV-a@sirena.org.uk No adjacent changes. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15tcp: rehash onto different local ECMP path on retransmit timeoutNeil Spring
Currently sk_rethink_txhash() re-rolls the socket's txhash on RTO, PLB, and spurious-retransmission events, but the cached route is reused and the new hash is not propagated into the ECMP path selection logic. Two changes are needed to make rehash select a different local ECMP path: 1. Add __sk_dst_reset() alongside sk_rethink_txhash() in tcp_write_timeout(), tcp_rcv_spurious_retrans(), and tcp_plb_check_rehash() so the cached dst is invalidated and the next transmit triggers a fresh route lookup. 2. Set fl6->mp_hash from sk_txhash (or tcp_rsk(req)->txhash for SYN/ACK retransmits and syncookies) in tcp_v6_connect(), inet6_sk_rebuild_header(), inet6_csk_route_req(), inet6_csk_route_socket(), tcp_v6_send_response(), and cookie_v6_check() so fib6_select_path() picks a path based on the new hash. The mp_hash override only applies to fib_multipath_hash_policy 0 (the default L3 policy). Its hash includes the flow label, but that is 0 by default -- np->flow_label is unset, and auto_flowlabels only computes the on-wire label later, per packet -- so flows to the same peer share one local path. Keying the hash on sk_txhash makes the local path per-connection and lets a rehash re-select it. Policies 1-3 are left unchanged. The mp_hash assignment is factored into a small helper, ip6_ecmp_set_mp_hash(), shared by inet6_csk_route_req(), inet6_csk_route_socket(), tcp_v6_connect(), inet6_sk_rebuild_header(), tcp_v6_send_response(), and cookie_v6_check(). It applies (txhash >> 1) ?: 1 for policy 0 (the >> 1 keeps mp_hash in the 31-bit range; ?: 1 keeps it non-zero, since 0 would fall back to rt6_multipath_hash()). inet6_csk_route_socket() calls it only for sk_protocol == IPPROTO_TCP so that non-TCP callers (e.g., L2TP via inet6_csk_xmit) fall through to rt6_multipath_hash() and retain their existing flow-key-based ECMP behavior. tcp_v6_send_response() also sets mp_hash from the response txhash so that a control packet (a RST from the full socket, or an ACK from a time-wait socket) selects the same local ECMP nexthop as the connection's txhash rather than falling back to the flow hash. The time-wait socket's tw_txhash is copied from sk_txhash when the connection enters TIME_WAIT, so it reflects any rehash that occurred. Setting mp_hash explicitly is necessary because the default ECMP hash derives from fl6->flowlabel via np->flow_label, which is not updated from sk_txhash (REPFLOW is off by default). ip6_make_flowlabel() cannot help either, as it runs after the route lookup. As a consequence, for policy 0 the local ECMP path of an IPv6 TCP flow follows sk_txhash even when fl6->flowlabel is non-zero, e.g. a reflected (REPFLOW) or explicitly set (IPV6_FLOWLABEL_MGR) flow label. This is intentional: only local path selection changes, so rehash can recover from a failed path; the on-wire flow label is unchanged. sk_set_txhash() is moved before ip6_dst_lookup_flow() in tcp_v6_connect() so the initial ECMP path is selected by the same txhash that subsequent route rebuilds will use. This avoids unintended path changes when the cached dst is naturally invalidated (e.g., by PMTU discovery or route changes). The rehash sites (tcp_write_timeout(), tcp_plb_check_rehash(), and tcp_rcv_spurious_retrans()) call __sk_rethink_txhash_reset_dst(), which re-rolls the txhash and, when it changed, drops the cached dst so the next transmit re-runs route selection. The dst reset is guarded by sk->sk_family == AF_INET6 since IPv4 ECMP does not currently use sk_txhash for path selection. For IPv4-mapped IPv6 sockets this produces a redundant dst reset on a cold path (RTO/PLB); the subsequent IPv4 route lookup returns the same result. The helper is deliberately separate from sk_rethink_txhash() itself: dst_negative_advice() calls sk_rethink_txhash() before its own dst op, so resetting the dst inside sk_rethink_txhash() would skip that op (e.g. rt6_remove_exception_rt()). For syncookies, cookie_init_sequence() computes the cookie value before route_req() and sets txhash so the SYN-ACK selects the same ECMP path that cookie_v6_check() will use when the full socket is created. cookie_tcp_reqsk_init() derives txhash from the cookie so the full socket's ECMP path matches the SYN-ACK. Both the SYN-ACK assignment in tcp_conn_request() and the full-socket assignment in cookie_tcp_reqsk_init() set txhash from the cookie for IPv4 and IPv6 alike. On IPv6 this drives ECMP path selection; on IPv4, which does not use sk_txhash for ECMP, it only affects TX-queue selection. That selection scales the hash by its high bits (reciprocal_scale()), which are uniform in the keyed secure_tcp_syn_cookie() output -- the MSS index only perturbs the low bits -- so the queue distribution matches net_tx_rndhash(). cookie_init_sequence() is split from the former version that also called tcp_synq_overflow() and incremented SYNCOOKIESSENT; those side effects are now in cookie_record_sent(), called after route_req() succeeds so they are not bumped when route_req() fails. cookie_record_sent() is guarded by CONFIG_SYN_COOKIES to match the guard on tcp_synq_overflow(). route_req() receives 0 as tw_isn for the syncookie path so that tcp_v6_init_req() still saves ireq->pktopts for REPFLOW flowlabel reflection and IPv6 cmsg options. The ecn_ok clear for syncookies without timestamps stays after tcp_ecn_create_request() so it takes precedence. Signed-off-by: Neil Spring <ntspring@meta.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260615042158.1600746-2-ntspring@meta.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15tcp: ipv6: clamp default adverting MSS to avoid GSO_BY_FRAGS (0xFFFF)Eric Dumazet
When MTU is large, ip6_default_advmss() can return IPV6_MAXPLEN (65535). This is interpreted by TCP as mss_clamp, allowing the MSS to reach 65535. However, 0xFFFF is also used as a magic value GSO_BY_FRAGS in the kernel. If a TCP packet with gso_size=0xFFFF is passed to skb_segment(), it will be mistakenly treated as GSO_BY_FRAGS, leading to a NULL pointer dereference because local TCP packets do not use frag_list. Fix this by returning min(IPV6_MAXPLEN, GSO_BY_FRAGS - 1) (65534) from ip6_default_advmss() when MTU is large. Also update the stale comment in ip6_default_advmss() which suggested that IPV6_MAXPLEN is returned to mean "any MSS". Fixes: 3953c46c3ac7 ("sk_buff: allow segmenting based on frag sizes") Reported-by: syzbot+ebdb22d461c904fc3cb2@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/6a2c3193.8812e0fc.3c3fa4.0001.GAE@google.com/T/#u Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260612162517.83394-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-13Merge tag 'ipsec-next-2026-06-12' of ↵Jakub Kicinski
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next Steffen Klassert says: ==================== pull request (net-next): ipsec-next 2026-06-12 1) Replace the open-coded manual cleanup in xfrm_add_policy() error path with xfrm_policy_destroy() for consistency with xfrm_policy_construct(). From Deepanshu Kartikey. 2) Limit XFRMA_TFCPAD to a sensible maximum (max IP length, 64k) since u32 is excessive for traffic flow confidentiality padding. From David Ahern. 3) Add a new netlink message XFRM_MSG_MIGRATE_STATE that allows migrating individual IPsec SAs independently of their policies. The existing XFRM_MSG_MIGRATE is tightly coupled to policy+SA migration, lacks SPI for unique SA identification, and cannot express reqid changes or migrate Transport mode selectors. The new interface identifies the SA via SPI and mark, supports reqid changes, address family changes, encap removal, and uses an atomic create+install flow under x->lock to prevent SN/IV reuse during AEAD SA migration. From Antony Antony. * tag 'ipsec-next-2026-06-12' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next: xfrm: add documentation for XFRM_MSG_MIGRATE_STATE xfrm: restrict netlink attributes for XFRM_MSG_MIGRATE_STATE xfrm: add XFRM_MSG_MIGRATE_STATE for single SA migration xfrm: make xfrm_dev_state_add xuo parameter const xfrm: extract address family and selector validation helpers xfrm: refactor XFRMA_MTIMER_THRESH validation into a helper xfrm: move encap and xuo into struct xfrm_migrate xfrm: add error messages to state migration xfrm: add state synchronization after migration xfrm: check family before comparing addresses in migrate xfrm: split xfrm_state_migrate into create and install functions xfrm: rename reqid in xfrm_migrate xfrm: fix NAT-related field inheritance in SA migration xfrm: allow migration from UDP encapsulated to non-encapsulated ESP xfrm: add extack to xfrm_init_state xfrm: remove redundant assignments xfrm: Reject excessive values for XFRMA_TFCPAD xfrm: cleanup error path in xfrm_add_policy() ==================== Link: https://patch.msgid.link/20260612074725.1760473-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-12ipv6: Honor oif when choosing nexthop for locally generated trafficIdo Schimmel
Commit 741a11d9e410 ("net: ipv6: Add RT6_LOOKUP_F_IFACE flag if oif is set") made the kernel honor the oif parameter when specified as part of output route lookup: # ip route add 2001:db8:1::/64 dev dummy1 # ip route add ::/0 dev dummy2 # ip route get 2001:db8:1::1 oif dummy2 fibmatch default dev dummy2 metric 1024 pref medium Due to regression reports, the behavior was partially reverted in commit d46a9d678e4c ("net: ipv6: Dont add RT6_LOOKUP_F_IFACE flag if saddr set") to only honor the oif if source address is not specified: # ip route get 2001:db8:1::1 from 2001:db8:2::1 oif dummy2 fibmatch 2001:db8:1::/64 dev dummy1 metric 1024 pref medium That is, when source address is specified, the kernel will choose the most specific route even if its nexthop device does not match the specified oif. This creates a problem for multipath routes. After looking up a route, when source address is not specified, the kernel will choose a nexthop whose nexthop device matches the specified oif: # sysctl -wq net.ipv6.conf.all.forwarding=1 # ip route add 2001:db8:10::/64 nexthop via fe80::1 dev dummy1 nexthop via fe80::2 dev dummy2 # for i in {1..100}; do ip route get 2001:db8:10::${i} oif dummy2; done | grep -o dummy[0-9] | sort | uniq -c 100 dummy2 But will disregard the oif when source address is specified despite the fact that a matching nexthop exists: # for i in {1..100}; do ip route get 2001:db8:10::${i} from 2001:db8:2::1 oif dummy2; done | grep -o dummy[0-9] | sort | uniq -c 53 dummy1 47 dummy2 This behavior differs from IPv4: # ip address add 192.0.2.1/32 dev lo # ip route add 198.51.100.0/24 nexthop via inet6 fe80::1 dev dummy1 nexthop via inet6 fe80::2 dev dummy2 # for i in {1..100}; do ip route get 198.51.100.${i} from 192.0.2.1 oif dummy2; done | grep -o dummy[0-9] | sort | uniq -c 100 dummy2 What happens is that fib6_table_lookup() returns a route with a matching nexthop device (assuming it exists): # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:10::${i} from 2001:db8:2::1 oif dummy2; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy2 But it is later overwritten during path selection in fib6_select_path() which instead chooses a nexthop according to the calculated hash. Solve this by telling fib6_select_path() to skip path selection if we have an oif match during output route lookup (iif being LOOPBACK_IFINDEX). Behavior after the change: # sysctl -wq net.ipv6.conf.all.forwarding=1 # ip route add 2001:db8:10::/64 nexthop via fe80::1 dev dummy1 nexthop via fe80::2 dev dummy2 # for i in {1..100}; do ip route get 2001:db8:10::${i} from 2001:db8:2::1 oif dummy2; done | grep -o dummy[0-9] | sort | uniq -c 100 dummy2 Note that enabling forwarding is only needed because we did not add neighbor entries for the gateway addresses. When forwarding is disabled and CONFIG_IPV6_ROUTER_PREF is not enabled in kernel config, the kernel will treat non-existing neighbor entries as errors and perform round-robin between the nexthops: # sysctl -wq net.ipv6.conf.all.forwarding=0 # for i in {1..100}; do ip route get 2001:db8:10::${i} from 2001:db8:2::1 oif dummy2; done | grep -o dummy[0-9] | sort | uniq -c 50 dummy1 50 dummy2 Reviewed-by: David Ahern <dsahern@kernel.org> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260611154605.992528-3-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-12ipv6: Select best matching nexthop object in fib6_table_lookup()Ido Schimmel
Currently, when using multipath routes without nexthop objects, fib6_table_lookup() selects the nexthop with the highest score. This means that when both a source address and an oif are specified, the nexthop that is chosen is the one that matches in terms of oif: # sysctl -wq net.ipv6.conf.all.forwarding=1 # ip address add 2001:db8:2::1/64 dev lo # ip route add 2001:db8:10::/64 nexthop via fe80::1 dev dummy1 nexthop via fe80::2 dev dummy2 # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:10::${i} from 2001:db8:2::1 oif dummy1; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy1 # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:10::${i} from 2001:db8:2::1 oif dummy2; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy2 When using nexthop objects, fib6_table_lookup() selects the first matching nexthop and not necessarily the one with the highest score: # ip nexthop add id 1 via fe80::1 dev dummy1 # ip nexthop add id 2 via fe80::2 dev dummy2 # ip nexthop add id 3 group 1/2 # ip route add 2001:db8:20::/64 nhid 3 # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:20::${i} from 2001:db8:2::1 oif dummy1; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy1 # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:20::${i} from 2001:db8:2::1 oif dummy2; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy1 This is not very significant right now because the nexthop is later overwritten during path selection in fib6_select_path(). However, the next patch is going to skip path selection when we have an oif match during output route lookup. As a preparation for this change, align the nexthop object behavior with the legacy one and make sure that fib6_table_lookup() always selects the best matching nexthop. Do that by always returning 0 from rt6_nh_find_match() in order not to terminate the loop in nexthop_for_each_fib6_nh() and storing in arg->nh the best matching nexthop so far. Behavior after the change: # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:20::${i} from 2001:db8:2::1 oif dummy1; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy1 # perf record -e fib6:fib6_table_lookup -- bash -c "for i in {1..100}; do ip route get 2001:db8:20::${i} from 2001:db8:2::1 oif dummy2; done > /dev/null" # perf script | grep -o dummy[0-9] | sort | uniq -c 100 dummy2 Signed-off-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20260611154605.992528-2-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-12ipv6: mcast: annotate igmp6 timer expiry raceYuyang Huang
/proc/net/igmp6 walks IPv6 multicast memberships under RCU and reads mca_work.timer.expires to print the remaining multicast timer. The delayed-work timer can be updated concurrently. Annotate the intentional lockless procfs snapshot with READ_ONCE(). Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260609081113.7613-3-sigefriedhyy@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-12ipv6: mcast: annotate data-races around mca_flagsYuyang Huang
/proc/net/igmp6 walks IPv6 multicast memberships under RCU and prints mca_flags without holding idev->mc_lock. The multicast paths update the field while holding idev->mc_lock. Annotate this intentional lockless snapshot with READ_ONCE() and the matching writers with WRITE_ONCE(). Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260609081113.7613-2-sigefriedhyy@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-12xfrm: Fix dev use-after-free in xfrm async resumptionDong Chenchen
xfrm async resumption hold skb->dev refcnt until after transport_finish. However, xfrm_rcv_cb may modify skb->dev to tunnel dev without taking device reference, such as vti_rcv_cb. The subsequent async resumption will decrement the tunnel device's reference count, which lead to uaf of tunnel dev and refcnt leak of orig dev as below: unregister_netdevice: waiting for vti1 to become free. Usage count = -2 Stash the original skb->dev to fix refcnt imbalance. The new skb->dev set by xfrm_rcv_cb can race with device teardown. Extend rcu protection over xfrm_rcv_cb and transport_finish to prevent races. Fixes: 1c428b038400 ("xfrm: hold dev ref until after transport_finish NF_HOOK") Reported-by: Xu Chunxiao <xuchunxiao3@huawei.com> Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
2026-06-11ip6_tunnel: annotate data-races around t->err_count and t->err_timeEric Dumazet
ip6_tnl_xmit() and ipip6_tunnel_xmit() run locklessly (dev->lltx == true). ip6gre_err() and ipip6_err() also run locklessly. We need to add READ_ONCE() and WRITE_ONCE() annotations around t->err_count and t->err_time. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260610171458.1359630-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-11ipmr: Convert mr_table.cache_resolve_queue_len to u32.Kuniyuki Iwashima
mr_table.cache_resolve_queue_len is always updated under spin_lock_bh(&mfc_unres_lock). Let's convert it to u32. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260609222013.1550355-1-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-11Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netJakub Kicinski
Cross-merge networking fixes after downstream PR (net-7.1-rc8). Conflicts: drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c f67aead16e85 ("net: txgbe: rework service event handling") 57d39faed4c9 ("net: txgbe: improve functions of AML 40G devices") net/rds/info.c 512db8267b73 ("rds: mark snapshot pages dirty in rds_info_getsockopt()") 6e94eeb2a2a6 ("rds: convert to getsockopt_iter") Adjacent changes: include/net/sock.h 1ee90b77b727 ("net: guard timestamp cmsgs to real error queue skbs") f0de88303d5e ("net: make is_skb_wmem() available to modules") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-11ip6_tunnel: do not use dst6_mtu() in ip4ip6_err() and ip6erspan_tunnel_xmit()Eric Dumazet
This is a minor performance / conceptual fix. 1) ip6erspan_tunnel_xmit() ERSPAN tunnel can mirror both IPv4 and IPv6 traffic, skb (the packet being mirrored) can be an IPv4 packet, and thus dst can be an IPv4 destination entry Use dst_mtu() which contains generic logic for both families. 2) ip4ip6_err() skb2 has been prepared as an IPv4 packet, and its destination is an IPv4 route. dst6_mtu() is optimized for IPv6 destinations and uses INDIRECT_CALL_1 to call ip6_mtu() directly if the ops match. We should use dst4_mtu() instead. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260609091337.2672441-1-edumazet@google.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-06-11Merge tag 'nf-26-06-10' of ↵Paolo Abeni
git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Revalidate bridge ports, add missing NULL checks to fetch the bridge device by the port. From Florian Westphal. 2) Fix netdevice refcount leak in the error path of nft_fwd hardware offload function, also from Florian. 3) Unregister helper expectfn callback on conntrack helper module removal, otherwise dangling pointer remains in place, from Weiming Shi. 4) Fix possible pointer infoleak in getsockopt() IPT_SO_GET_ENTRIES, From Kyle Zeng. 5) Validate that device MAC header is present before nf_syslog accesses it. From Xiang Mei. 6-8) Three patches to address a possible infoleak of stale stack data in three nf_tables expressions, due to mismatch in the _init() and _eval() function which is possible since 14fb07130c7d. From Davide Ornaghi and Florian Westphal. netfilter pull request 26-06-10 * tag 'nf-26-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nft_meta_bridge: fix stale stack leak via IIFHWADDR register netfilter: nft_fib: fix stale stack leak via the OIFNAME register netfilter: nft_exthdr: fix register tracking for F_PRESENT flag netfilter: nf_log: validate MAC header was set before dumping it netfilter: x_tables: avoid leaking percpu counter pointers netfilter: nf_conntrack: destroy stale expectfn expectations on unregister netfilter: nf_tables_offload: drop device refcount on error netfilter: revalidate bridge ports ==================== Link: https://patch.msgid.link/20260610161629.214092-1-pablo@netfilter.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-06-11Merge tag 'ipsec-2026-06-10' of ↵Paolo Abeni
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec Steffen Klassert says: ==================== pull request (net): ipsec 2026-06-10 1) xfrm: iptfs: preserve shared-frag marker in iptfs_consume_frags() Propagate SKBFL_SHARED_FRAG when paged fragments are moved between skbs so ESP can decide whether in-place crypto is safe. 2) xfrm: iptfs: fix use-after-free on first_skb in __input_process_payload Replace the unlocked read of xtfs->ra_newskb with a local flag so a concurrent reassembly can no longer free first_skb between spin_unlock and the post-loop check. 3) xfrm: policy: fix use-after-free on inexact bin in xfrm_policy_bysel_ctx() Prune the inexact bin under xfrm_policy_lock so a concurrent xfrm_hash_rebuild() can no longer free it before xfrm_policy_kill() dereferences it. 4) xfrm: iptfs: fix ABBA deadlock in iptfs_destroy_state() Move hrtimer_cancel() for the output and drop timers ahead of their spinlocks, breaking the softirq/lock cycle that could deadlock against the timer callbacks on SMP. 5) xfrm: espintcp: do not reuse an in-progress partial send Fail a new send when espintcp_push_msgs() returns with emsg->len still set, so a blocking caller can no longer overwrite ctx->partial while a previous transfer still owns it. 6) esp: fix page frag reference leak on skb_to_sgvec failure Add a flag to esp_ssg_unref() to unconditionally unref the source scatterlist, releasing the old page references that are otherwise leaked when the second skb_to_sgvec() in esp_output_tail() fails. Please pull or let me know if there are problems. ipsec-2026-06-10 * tag 'ipsec-2026-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: esp: fix page frag reference leak on skb_to_sgvec failure xfrm: espintcp: do not reuse an in-progress partial send xfrm: iptfs: fix ABBA deadlock in iptfs_destroy_state() xfrm: policy: fix use-after-free on inexact bin in xfrm_policy_bysel_ctx() xfrm: iptfs: fix use-after-free on first_skb in __input_process_payload xfrm: iptfs: preserve shared-frag marker in iptfs_consume_frags() ==================== Link: https://patch.msgid.link/20260610140800.2562818-1-steffen.klassert@secunet.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-06-11ipv6: Fix a potential NPD in cleanup_prefix_route()Ido Schimmel
addrconf_get_prefix_route() can return the fib6_null_entry sentinel entry which has a NULL fib6_table pointer. Therefore, before setting the route's expiration time, check that we are not working with this entry, as otherwise a NPD will be triggered [1]. Note that the other callers of addrconf_get_prefix_route() are not susceptible to this bug: 1. addrconf_prefix_rcv(): Requests a route with the 'RTF_ADDRCONF | RTF_PREFIX_RT' flags which are not set on fib6_null_entry. 2. modify_prefix_route(): Fixed by commit a747e02430df ("ipv6: avoid possible NULL deref in modify_prefix_route()"). 3. __ipv6_ifa_notify(): Calls ip6_del_rt() which specifically checks for fib6_null_entry and returns an error. [1] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037] [...] Call Trace: <TASK> __kasan_check_byte (mm/kasan/common.c:573) lock_acquire.part.0 (kernel/locking/lockdep.c:5842 (discriminator 1)) _raw_spin_lock_bh (kernel/locking/spinlock.c:182 (discriminator 1)) cleanup_prefix_route (net/ipv6/addrconf.c:1280) ipv6_del_addr (net/ipv6/addrconf.c:1342) inet6_addr_del.isra.0 (net/ipv6/addrconf.c:3119) inet6_rtm_deladdr (net/ipv6/addrconf.c:4812) rtnetlink_rcv_msg (net/core/rtnetlink.c:6997) netlink_rcv_skb (net/netlink/af_netlink.c:2555) netlink_unicast (net/netlink/af_netlink.c:1344) netlink_sendmsg (net/netlink/af_netlink.c:1899) __sock_sendmsg (net/socket.c:802 (discriminator 4)) ____sys_sendmsg (net/socket.c:2698) ___sys_sendmsg (net/socket.c:2752) __sys_sendmsg (net/socket.c:2784) do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.") Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com> Reviewed-by: David Ahern <dahern@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260609145448.768318-1-idosch@nvidia.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-06-10netfilter: nft_fib: fix stale stack leak via the OIFNAME registerDavide Ornaghi
For NFT_FIB_RESULT_OIFNAME the destination register is declared with len = IFNAMSIZ (four 32-bit registers), but on the lookup-fail, RTN_LOCAL and oif-mismatch paths nft_fib{4,6}_eval() only writes one register via "*dest = 0". The remaining three registers are left as whatever was on the stack in nft_do_chain()'s struct nft_regs, and a downstream expression that loads the register span can leak that uninitialised kernel stack to userspace. The NFTA_FIB_F_PRESENT existence check has the same shape: it is only meaningful for NFT_FIB_RESULT_OIF, yet it was accepted for any result type while the eval stores a single byte via nft_reg_store8(), leaving the rest of the declared span stale. Fix both: - replace the bare "*dest = 0" in the eval with nft_fib_store_result(), which strscpy_pad()s the whole IFNAMSIZ for OIFNAME (and is already used on the other early-return path), and - restrict NFTA_FIB_F_PRESENT to NFT_FIB_RESULT_OIF and declare its destination as a single u8, so the marked span matches the one byte the eval writes. Fixes: f6d0cbcf09c5 ("netfilter: nf_tables: add fib expression") Suggested-by: Florian Westphal <fw@strlen.de> Cc: stable@vger.kernel.org Signed-off-by: Davide Ornaghi <d.ornaghi97@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2026-06-10netfilter: x_tables: avoid leaking percpu counter pointersKyle Zeng
The native and compat get-entries paths copy the fixed rule entry header from the kernelized rule blob to userspace before overwriting the entry's counter fields with a sanitized counter snapshot. On SMP kernels, entry->counters.pcnt contains the percpu allocation address used by x_tables rule counters. A caller can provide a userspace buffer that faults during the initial fixed-header copy after pcnt has been copied but before the later sanitized counter copy runs. The syscall then returns -EFAULT while leaving the raw percpu pointer in userspace. Copy only the fixed entry prefix before counters from the kernelized rule blob, then copy the sanitized counter snapshot into the counter field. Apply this ordering to the IPv4, IPv6, and ARP native and compat get-entries implementations so a fault cannot expose the internal percpu counter pointer. Fixes: 71ae0dff02d7 ("netfilter: xtables: use percpu rule counters") Signed-off-by: Kyle Zeng <kylebot@openai.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2026-06-10ip6_vti: fix incorrect tunnel matching in vti6_tnl_lookup()Eric Dumazet
In vti6_tnl_lookup(), when an exact match for a tunnel fails, the code falls back to searching for wildcard tunnels: - Tunnels matching the packet's local address, with any remote address wildcard remote). - Tunnels matching the packet's remote address, with any local address (wildcard local). However, vti6 stores all these different types of tunnels in the same hash table (ip6n->tnls_r_l) prone to hash collisions. The bug is that the fallback search loops in vti6_tnl_lookup() were missing checks to ensure that the candidate tunnel actually has a wildcard address. Fixes: fbe68ee87522 ("vti6: Add a lookup method for tunnels with wildcard endpoints.") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Steffen Klassert <steffen.klassert@secunet.com> Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Link: https://patch.msgid.link/20260608164613.933023-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-09ip6_vti: set netns_immutable on the fallback device.Eric Dumazet
john1988 and Noam Rathaus reported that vti6_init_net() does not set the netns_immutable flag on the per-netns fallback tunnel device (ip6_vti0). Other similar tunnel drivers (like ip6_tunnel, sit, ip6_gre, and ip_tunnel) correctly set this flag during their fallback device initialization to prevent them from being moved to another network namespace. Fixes: 61220ab34948 ("vti6: Enable namespace changing") Reported-by: Noam Rathaus <noamr@ssd-disclosure.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Steffen Klassert <steffen.klassert@secunet.com> Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Link: https://patch.msgid.link/20260608155918.787644-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-09esp: fix page frag reference leak on skb_to_sgvec failureAlessandro Schino
In esp_output_tail(), when esp->inplace is false, the old skb page frags are replaced with a new page from the xfrm page_frag cache The source scatterlist (sg) is built from the old frags before the replacement, and esp_ssg_unref() is responsible for releasing the old page references after the crypto operation completes However, if the second skb_to_sgvec() call (which builds the destination scatterlist from the new page) fails, the code jumps to error_free which only calls kfree(tmp). The old page frag references captured in the source scatterlist are never released: 1 sg[] is built from old frags via skb_to_sgvec() (no extra get_page) 2 nr_frags is set to 1 and frag[0] is replaced with the new page 3 Second skb_to_sgvec() fails -> goto error_free Fix this by adding a bool parameter to esp_ssg_unref() that, when true, unconditionally unrefs the source scatterlist frags. Since req->src is not yet initialized by aead_request_set_crypt() at the point of the error, the source scatterlist is obtained directly via esp_req_sg() Existing callers pass false to preserve the original behavior The same issue exists in both esp4 and esp6 as the code is identical Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible") Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible") Signed-off-by: Alessandro Schino <7991aleschino@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
2026-06-08ipv6: sit: reload inner IPv6 header after GSO offloadsKyle Zeng
ipip6_tunnel_xmit() caches the inner IPv6 header pointer at function entry and continues using it after iptunnel_handle_offloads(). For GSO skbs, iptunnel_handle_offloads() calls skb_header_unclone(). When the skb header is cloned, skb_header_unclone() can call pskb_expand_head(), which may move the skb head. The pskb_expand_head() contract requires pointers into the skb header to be reloaded after the call. If the later skb_realloc_headroom() branch is not taken, SIT uses the stale iph6 pointer to read the inner hop limit and DS field. That can read from a freed skb head after the old head's remaining clone is released. Reload iph6 after the offload helper succeeds and before subsequent reads from the inner IPv6 header. Keep the existing reload after skb_realloc_headroom(), since that branch can also replace the skb. Fixes: 14909664e4e1 ("sit: Setup and TX path for sit/UDP foo-over-udp encapsulation") Signed-off-by: Kyle Zeng <kylebot@openai.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reported-by: syzbot+6eb9ca986d80f6f88cf9@syzkaller.appspotmail.com Link: https://patch.msgid.link/20260605073448.6524-1-kylebot@openai.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Replace RTNL with a dedicated mutex for MFC.Kuniyuki Iwashima
ip6mr does not have rtnetlink interface for MFC unlike ipmr, which uses dev_get_by_index_rcu() to set struct mfcctl.mfcc_parent. ip6mr_mfc_add() and ip6mr_mfc_delete() are called under RTNL from ip6_mroute_setsockopt() only. There are no RTNL dependant, but ip6_mroute_setsockopt() reuses RTNL just for mrt->mfc_hash and mrt->mfc_cache_list. Let's replace RTNL with a new per-netns mutex. Later, ip6mr_notifier_ops and ipmr_seq will be moved under CONFIG_IPV6_MROUTE. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-15-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Remove RTNL in ip6mr_rules_init() and ip6mr_net_init().Kuniyuki Iwashima
When ip6mr_free_table() is called from ip6mr_rules_init() or ip6mr_net_init(), the netns is not yet published. Thus, no device should have been registered, and mroute_clean_tables() will not call mif6_delete(), so unregister_netdevice_many() is unnecessary. unregister_netdevice_many() does nothing if the list is empty, but it requires RTNL due to the unconditional ASSERT_RTNL() at the entry of unregister_netdevice_many_notify(). Let's remove unnecessary RTNL and ASSERT_RTNL() and instead add WARN_ON_ONCE() in ip6mr_free_table(). Note that we use a local list for the new WARN_ON_ONCE() because dev_kill_list passed from ip6mr_rules_exit_rtnl() may have some devices when other ops->init() fails after ipmr durnig setup_net(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-14-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Convert ip6mr_net_exit_batch() to ->exit_rtnl().Kuniyuki Iwashima
ip6mr_net_ops uses ->exit_batch() to acquire RTNL only once for dying network namespaces. ip6mr does not depend on the ordering of ->exit_rtnl() and ->exit_batch() of other pernet_operations (unlike fib_net_ops). Once ip6mr_free_table() is called and all devices are queued for destruction in ->exit_rtnl(), later during NETDEV_UNREGISTER, ip6mr_device_event() will not see anything in vif table and just do nothing. Let's convert ip6mr_net_exit_batch() to ->exit_rtnl(). We will remove RTNL and unregister_netdevice_many() in ip6mr_rules_init(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-13-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Move unregister_netdevice_many() out of ip6mr_free_table().Kuniyuki Iwashima
This is a prep commit to convert ip6mr_net_exit_batch() to ->exit_rtnl(). Let's move unregister_netdevice_many() in ip6mr_free_table() to its callers. Now ip6mr_rules_exit() can do batching all tables per netns. Note that later we will remove RTNL and unregister_netdevice_many() in ip6mr_rules_init(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-12-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Move unregister_netdevice_many() out of mroute_clean_tables().Kuniyuki Iwashima
This is a prep commit to convert ip6mr_net_exit_batch() to ->exit_rtnl(). Let's move unregister_netdevice_many() in mroute_clean_tables() to its callers. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-11-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Call fib_rules_unregister() without RTNL.Kuniyuki Iwashima
fib_rules_unregister() removes ops from net->rules_ops under spinlock, calls ops->delete() for each rule, and frees the ops. ip6mr_rules_ops_template does not have ->delete(), and any operation does not require RTNL there. Let's move fib_rules_unregister() from ip6mr_rules_exit() to ip6mr_net_exit(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-10-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Free mr_table after RCU grace period.Kuniyuki Iwashima
Since default_device_exit_batch() is called after ->exit_rtnl(), idev->mc_ifc_work could finally call mroute6_is_socket() under RCU while ->exit_rtnl() is running. [0] With CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=n, ip6mr_fib_lookup() does not check if net->ipv6.mrt6 is NULL. If ip6mr_net_exit_batch() set net->ipv6.mrt6 to NULL and freed it, the mrt->mroute_sk access could result in null-ptr-deref or use-after-free. Let's prepare for that situation by applying RCU rule to ip6mr table similarly. !check_net(net) is added in ip6mr_cache_unresolved() and mroute_clean_tables() to synchronise the two by mfc_unres_lock so that ip6mr_cache_unresolved() will not queue skb after mroute_clean_tables() purged &mrt->mfc_unres_queue. rcu_read_lock() in reg_vif_xmit() is moved up to cover ip6mr_fib_lookup() as with ipmr. Link: https://lore.kernel.org/netdev/20260407184202.34cfe2d6@kernel.org/ #[0] Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-9-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08net: Remove rtnl_held of struct fib_dump_filter.Kuniyuki Iwashima
Commit 22e36ea9f5d7 ("inet: allow ip_valid_fib_dump_req() to be called with RTNL or RCU") introduced the rtnl_held field in struct fib_dump_filter to switch __dev_get_by_index() and dev_get_by_index_rcu() depending on the caller's context. This field served as an interim measure while we were incrementally converting all callers of ip_valid_fib_dump_req() to RCU. Now that all users (IPv4, IPv6, ipmr, ip6mr, and MPLS) have been converted to RCU, the field is no longer necessary. Let's remove it. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-8-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-08ip6mr: Convert ip6mr_rtm_dumproute() to RCU.Kuniyuki Iwashima
ip6mr_rtm_dumproute() calls mr_table_dump() or mr_rtm_dumproute(), and mr_rtm_dumproute() finally calls mr_table_dump(). mr_table_dump() calls the passed function, _ip6mr_fill_mroute(). _ip6mr_fill_mroute() is a wrapper for ip6mr_fill_mroute() to cast struct mr_mfc * to struct mfc6_cache *. ip6mr_fill_mroute() can already be called safely under RCU. Let's convert ip6mr_rtm_dumproute() to RCU. Now there is no user of the rtnl_held field in struct fib_dump_filter, and the next patch will remove it. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-7-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>