Files
linux/include/linux
Eric Dumazet 2987ee196c igmp: convert struct ip_sf_list to RCU
Commit 23d2b94043 ("igmp: Add ip_mc_list lock in ip_check_mc_rcu")
added spin_lock_bh(&im->lock) to ip_check_mc_rcu() to prevent a
use-after-free while iterating im->sources during concurrent deletions.

However, ip_check_mc_rcu() is called from RCU read-side critical
sections in packet receive and route lookup fast paths (e.g.
__mkroute_output(), ip_route_input_rcu(), and __udp4_lib_rcv()).

When igmpv3_send_cr() or igmpv3_send_report() holds &pmc->lock and
calls add_grec() -> igmpv3_newpack() -> ip_route_output_ports(),
an XFRM policy matching a multicast destination triggers
xfrm_tmpl_resolve_one() -> xfrm4_get_saddr() -> __mkroute_output() ->
ip_check_mc_rcu(). This attempts to acquire &im->lock while &pmc->lock
is already held on the same CPU, triggering a lockdep recursive locking
warning / deadlock.

Fix this by converting IPv4 struct ip_sf_list to RCU, mirroring the
IPv6 implementation in net/ipv6/mcast.c:

1. Add struct rcu_head to struct ip_sf_list and annotate sf_next,
   sources, and tomb as __rcu pointers.
2. Use rcu_assign_pointer() and kfree_rcu() for list updates and
   deletions.
3. Remove spin_lock_bh(&im->lock) from ip_check_mc_rcu() and traverse
   im->sources locklessly with for_each_psf_rcu(), reading and writing
   counter fields with READ_ONCE() and WRITE_ONCE().

Note: RCU conversion of /proc/net/mcfilter will be done in a
separate patch.

Fixes: 23d2b94043 ("igmp: Add ip_mc_list lock in ip_check_mc_rcu")
Reported-by: syzbot+3d99fb01bcd740f2fc1e@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3d99fb01bcd740f2fc1e
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260827160656.903003-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-31 17:22:03 -07:00
..
2026-07-23 10:24:12 -07:00
2026-08-07 14:18:13 -03:00
2026-04-02 15:52:49 +02:00
2026-05-21 13:04:42 +02:00
2026-03-19 23:55:27 +01:00
2026-05-28 21:24:54 -07:00
2026-08-10 18:00:47 +01:00
2026-07-29 17:54:58 -07:00
2026-08-04 19:18:48 -07:00
2026-04-03 16:53:50 -04:00
2026-08-15 17:09:32 -06:00
2026-08-15 23:36:18 +02:00
2026-06-07 10:03:01 -07:00
2026-07-27 16:25:34 +02:00
2026-08-06 06:47:33 -06:00
2026-07-28 11:25:30 -04:00
2026-07-07 15:10:48 -04:00
2026-05-28 17:45:46 -07:00
2026-06-05 00:34:55 -04:00
2026-05-18 11:16:29 +02:00
2026-05-28 11:36:59 -04:00
2026-06-05 17:46:17 -07:00
2026-08-31 17:22:03 -07:00
2026-05-28 21:24:43 -07:00
2026-04-05 13:53:28 -07:00
2026-04-01 10:19:41 +02:00
2026-07-31 10:09:12 +02:00
2026-04-03 16:53:50 -04:00
2026-06-30 00:15:52 +01:00
2026-03-18 09:59:57 +00:00
2026-08-24 18:42:50 -07:00
2026-07-23 15:42:48 +02:00
2026-08-12 16:24:26 +02:00
2026-06-26 22:18:34 -04:00
2026-07-28 21:11:47 -07:00
2026-04-05 13:53:10 -07:00
2026-04-20 11:35:17 -07:00
2026-08-05 11:20:12 -07:00
2026-08-05 11:20:12 -07:00
2026-07-23 19:21:13 +01:00
2026-03-31 07:04:00 -06:00
2026-08-15 23:36:18 +02:00
2026-07-15 15:34:25 -07:00
2026-07-15 15:34:25 -07:00
2026-08-24 18:43:26 -07:00
2026-07-27 17:18:00 +02:00
2026-05-11 16:59:43 +02:00
2026-07-31 16:22:52 -04:00
2026-07-13 07:09:28 +02:00
2026-06-06 15:22:44 +02:00