linux/net/ipv6
Jiayuan Chen f723ccaff2 ipv6: anycast: insert aca into global hash under idev->lock
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: eb1ac9ff6c ("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>
History 2026-06-02 19:30:39 -07:00
..
ila net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
netfilter netfilter: nft_fib_ipv6: bail out of sibling walk if rt got unlinked 2026-06-01 13:43:52 +02:00
addrconf.c Revert "ipv6: preserve insertion order for same-scope addresses" 2026-05-29 13:00:54 -07:00
addrconf_core.c ipv6: remove ipv6_stub infrastructure completely 2026-03-29 11:21:24 -07:00
addrlabel.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
af_inet6.c tcp: update window_clamp when SO_RCVBUF is set 2026-04-13 15:32:35 +02:00
ah6.c xfrm: ah: use skb_to_full_sk in async output callbacks 2026-05-16 10:56:14 +02:00
anycast.c ipv6: anycast: insert aca into global hash under idev->lock 2026-06-02 19:30:39 -07:00
calipso.c Convert remaining multi-line kmalloc_obj/flex GFP_KERNEL uses 2026-02-22 08:26:33 -08:00
datagram.c ipv6: validate extension header length before copying to cmsg 2026-05-26 18:53:10 -07:00
esp6.c Revert "esp: fix page frag reference leak on skb_to_sgvec failure" 2026-05-29 10:23:25 +02:00
esp6_offload.c xfrm: Fix inner mode lookup in tunnel mode GSO segmentation 2025-12-04 09:54:53 +01:00
exthdrs.c ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress() 2026-05-27 19:05:53 -07:00
exthdrs_core.c ipv6: Implement limits on extension header parsing 2026-04-30 17:21:45 -07:00
exthdrs_offload.c net: gso: add HBH extension header offload support 2024-01-05 08:11:49 -08:00
fib6_notifier.c net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
fib6_rules.c ipv6: export fib6_lookup for nft_fib_ipv6 2026-03-04 11:45:44 +01:00
fou6.c fou: Remove IPPROTO_UDPLITE check in gue_err() and gue6_err(). 2026-03-17 16:10:59 -07:00
icmp.c ipv6: fix possible UAF in icmpv6_rcv() 2026-04-18 12:09:52 -07:00
inet6_connection_sock.c tcp: move inet6_csk_update_pmtu() to tcp_ipv6.c 2026-02-24 17:47:27 -08:00
inet6_hashtables.c tcp: use __jhash_final() in inet6_ehashfn() 2026-03-29 11:45:48 -07:00
ioam6.c net: ioam6: fix OOB and missing lock 2026-04-08 19:08:56 -07:00
ioam6_iptunnel.c ipv6: ioam: fix heap buffer overflow in __ioam6_fill_trace_data() 2026-02-13 12:24:05 -08:00
ip6_checksum.c udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV. 2026-03-13 18:57:45 -07:00
ip6_fib.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-04-02 11:03:13 -07:00
ip6_flowlabel.c ipv6: flowlabel: enforce per-netns limit for unprivileged callers 2026-05-08 14:59:14 -07:00
ip6_gre.c ip6_gre: Use cached t->net in ip6erspan_changelink(). 2026-05-02 10:36:21 -07:00
ip6_icmp.c ipv6: remove dynamic ICMPv6 sender registration infrastructure 2026-03-29 11:21:23 -07:00
ip6_input.c ipv6: Implement limits on extension header parsing 2026-04-30 17:21:45 -07:00
ip6_offload.c ipv6: replace IS_BUILTIN(CONFIG_IPV6) with IS_ENABLED(CONFIG_IPV6) 2026-03-29 11:21:23 -07:00
ip6_offload.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
ip6_output.c ipv6: fix potential UAF caused by ip6_forward_proxy_check() 2026-05-06 17:29:23 -07:00
ip6_tunnel.c ipv6: Implement limits on extension header parsing 2026-04-30 17:21:45 -07:00
ip6_udp_tunnel.c ipv6: remove ipv6_stub infrastructure completely 2026-03-29 11:21:24 -07:00
ip6_vti.c ip6: vti: Use ip6_tnl.net in vti6_siocdevprivate(). 2026-05-26 11:16:12 +02:00
ip6mr.c ipmr/ip6mr: Convert net->ipv[46].ipmr_seq to atomic_t. 2026-03-02 18:49:41 -08:00
ipcomp6.c xfrm: delete x->tunnel as we delete x 2025-07-08 13:28:27 +02:00
ipv6_sockglue.c ipv6: Remove UDP-Lite support for IPV6_ADDRFORM. 2026-03-13 18:57:44 -07:00
Kconfig ipv6: default IPV6_SIT to m 2026-05-05 17:31:51 -07:00
Makefile ipv6: Retire UDP-Lite. 2026-03-13 18:57:44 -07:00
mcast.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
mcast_snoop.c net: bridge: mcast: fix broken length + header check for MRDv6 Adv. 2021-04-27 14:02:06 -07:00
mip6.c net: fill in MODULE_DESCRIPTION()s for ipv6 modules 2024-02-09 14:12:01 -08:00
ndisc.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-04-02 11:03:13 -07:00
netfilter.c netfilter: remove nf_ipv6_ops and use direct function calls 2026-03-29 11:21:24 -07:00
output_core.c ipv6: move ip6_dst_hoplimit() to net/ipv6/ip6_output.c 2026-04-01 18:50:35 -07:00
ping.c net: remove addr_len argument of recvmsg() handlers 2026-03-02 18:17:17 -08:00
proc.c udp: Remove UDP-Lite SNMP stats. 2026-03-13 18:57:44 -07:00
protocol.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
raw.c net: change sock_queue_rcv_skb_reason() to return a drop_reason 2026-04-12 14:30:25 -07:00
reassembly.c ipv6: discard fragment queue earlier if there is malformed datagram 2026-02-27 19:08:54 -08:00
route.c ipv6: fix possible infinite loop in fib6_select_path() 2026-05-29 12:41:00 -07:00
rpl.c ipv6: rpl: Remove pskb(_may)?_pull() in ipv6_rpl_srh_rcv(). 2023-06-19 11:32:58 -07:00
rpl_iptunnel.c net: ipv6: fix NOREF dst use in seg6 and rpl lwtunnels 2026-04-28 11:16:14 +02:00
seg6.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seg6_hmac.c ipv6: add NULL checks for idev in SRv6 paths 2026-03-18 17:23:43 -07:00
seg6_iptunnel.c net: ipv6: fix NOREF dst use in seg6 and rpl lwtunnels 2026-04-28 11:16:14 +02:00
seg6_local.c ipv6: adopt dst_dev() helper 2025-07-02 14:32:30 -07:00
sit.c ipv6: sit: remove redundant ret = 0 assignment 2026-04-09 20:37:40 -07:00
syncookies.c tcp: secure_seq: add back ports to TS offset 2026-03-04 17:44:35 -08:00
sysctl_net_ipv6.c sysctl: treewide: constify the ctl_table argument of proc_handlers 2024-07-24 20:59:29 +02:00
tcp_ao.c net/tcp: Wire up l3index to TCP-AO 2023-10-27 10:35:46 +01:00
tcp_ipv6.c tcp: fix stale per-CPU tcp_tw_isn leak enabling ISN prediction 2026-05-20 19:14:06 -07:00
tcpv6_offload.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-01-29 17:28:54 -08:00
tunnel6.c net: fill in MODULE_DESCRIPTION()s for ipv6 modules 2024-02-09 14:12:01 -08:00
udp.c udp: Force compute_score to always inline 2026-04-13 15:44:42 -07:00
udp_offload.c udp: Don't pass udptable to IPv6 socket lookup functions. 2026-03-13 18:57:46 -07:00
xfrm6_input.c xfrm: hold dev ref until after transport_finish NF_HOOK 2026-04-07 10:12:40 +02:00
xfrm6_output.c ipv6: adopt skb_dst_dev() and skb_dst_dev_net[_rcu]() helpers 2025-07-02 14:32:30 -07:00
xfrm6_policy.c xfrm6: fix uninitialized saddr in xfrm6_get_saddr() 2026-02-02 08:03:47 +01:00
xfrm6_protocol.c ipv6: xfrm6: release dst on error in xfrm6_rcv_encap() 2026-04-17 10:40:29 +02:00
xfrm6_state.c xfrm: remove output_finish indirection from xfrm_state_afinfo 2020-05-06 09:40:08 +02:00
xfrm6_tunnel.c xfrm: flush all states in xfrm_state_fini 2025-08-06 09:23:38 +02:00