mirror-linux/net/ipv6
Andrea Mayer f9c52a6ba9 net: ipv6: fix NOREF dst use in seg6 and rpl lwtunnels
seg6_input_core() and rpl_input() call ip6_route_input() which sets a
NOREF dst on the skb, then pass it to dst_cache_set_ip6() invoking
dst_hold() unconditionally.
On PREEMPT_RT, ksoftirqd is preemptible and a higher-priority task can
release the underlying pcpu_rt between the lookup and the caching
through a concurrent FIB lookup on a shared nexthop.
Simplified race sequence:

  ksoftirqd/X                       higher-prio task (same CPU X)
  -----------                       --------------------------------
  seg6_input_core(,skb)/rpl_input(skb)
    dst_cache_get()
      -> miss
    ip6_route_input(skb)
      -> ip6_pol_route(,skb,flags)
         [RT6_LOOKUP_F_DST_NOREF in flags]
        -> FIB lookup resolves fib6_nh
           [nhid=N route]
        -> rt6_make_pcpu_route()
           [creates pcpu_rt, refcount=1]
             pcpu_rt->sernum = fib6_sernum
             [fib6_sernum=W]
           -> cmpxchg(fib6_nh.rt6i_pcpu,
                      NULL, pcpu_rt)
              [slot was empty, store succeeds]
      -> skb_dst_set_noref(skb, dst)
         [dst is pcpu_rt, refcount still 1]

                                    rt_genid_bump_ipv6()
                                      -> bumps fib6_sernum
                                         [fib6_sernum from W to Z]
                                    ip6_route_output()
                                      -> ip6_pol_route()
                                        -> FIB lookup resolves fib6_nh
                                           [nhid=N]
                                        -> rt6_get_pcpu_route()
                                             pcpu_rt->sernum != fib6_sernum
                                             [W <> Z, stale]
                                          -> prev = xchg(rt6i_pcpu, NULL)
                                          -> dst_release(prev)
                                             [prev is pcpu_rt,
                                              refcount 1->0, dead]

    dst = skb_dst(skb)
    [dst is the dead pcpu_rt]
    dst_cache_set_ip6(dst)
      -> dst_hold() on dead dst
      -> WARN / use-after-free

For the race to occur, ksoftirqd must be preemptible (PREEMPT_RT without
PREEMPT_RT_NEEDS_BH_LOCK) and a concurrent task must be able to release
the pcpu_rt. Shared nexthop objects provide such a path, as two routes
pointing to the same nhid share the same fib6_nh and its rt6i_pcpu
entry.

Fix seg6_input_core() and rpl_input() by calling skb_dst_force() after
ip6_route_input() to force the NOREF dst into a refcounted one before
caching.
The output path is not affected as ip6_route_output() already returns a
refcounted dst.

Fixes: af4a2209b1 ("ipv6: sr: use dst_cache in seg6_input")
Fixes: a7a29f9c36 ("net: ipv6: add rpl sr tunnel")
Cc: stable@vger.kernel.org
Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Justin Iurman <justin.iurman@gmail.com>
Link: https://patch.msgid.link/20260421094735.20997-1-andrea.mayer@uniroma2.it
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-04-28 11:16:14 +02:00
..
ila net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
netfilter netfilter: nat: use kfree_rcu to release ops 2026-04-20 23:45:41 +02:00
Kconfig ipv6: convert CONFIG_IPV6 to built-in only and clean up Kconfigs 2026-03-29 11:21:22 -07:00
Makefile ipv6: Retire UDP-Lite. 2026-03-13 18:57:44 -07:00
addrconf.c Networking changes for 7.1. 2026-04-14 18:36:10 -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 Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
anycast.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
calipso.c Convert remaining multi-line kmalloc_obj/flex GFP_KERNEL uses 2026-02-22 08:26:33 -08:00
datagram.c Networking changes for 7.1. 2026-04-14 18:36:10 -07:00
esp6.c esp: fix skb leak with espintcp and async crypto 2026-02-25 09:11:40 +01: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: reserve mac_len headroom when recompressed SRH grows 2026-04-27 17:47:26 -07:00
exthdrs_core.c
exthdrs_offload.c
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 net: ipv6: flowlabel: defer exclusive option free until RCU teardown 2026-03-31 15:44:29 -07:00
ip6_gre.c gre: Count GRE packet drops 2026-04-12 12:33:33 -07:00
ip6_icmp.c ipv6: remove dynamic ICMPv6 sender registration infrastructure 2026-03-29 11:21:23 -07:00
ip6_input.c tcp: move tcp_v6_early_demux() to net/ipv6/ip6_input.c 2026-03-05 18:33:51 -08: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
ip6_output.c ipv6: move ip6_dst_hoplimit() to net/ipv6/ip6_output.c 2026-04-01 18:50:35 -07:00
ip6_tunnel.c ipv6: Cap TLV scan in ip6_tnl_parse_tlv_enc_lim 2026-04-23 11:52:07 -07:00
ip6_udp_tunnel.c ipv6: remove ipv6_stub infrastructure completely 2026-03-29 11:21:24 -07:00
ip6_vti.c ipv6: adopt skb_dst_dev() and skb_dst_dev_net[_rcu]() helpers 2025-07-02 14:32:30 -07: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
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
mip6.c
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
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: prepare headers for ipv6_stub removal 2026-03-29 11:21:23 -07:00
rpl.c
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
tcp_ipv6.c Networking changes for 7.1. 2026-04-14 18:36:10 -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
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
xfrm6_state.c
xfrm6_tunnel.c xfrm: flush all states in xfrm_state_fini 2025-08-06 09:23:38 +02:00