]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipv4: igmp: annotate data-races around im->users
authorYuyang Huang <sigefriedhyy@gmail.com>
Fri, 22 May 2026 09:39:06 +0000 (18:39 +0900)
committerJakub Kicinski <kuba@kernel.org>
Mon, 25 May 2026 18:08:59 +0000 (11:08 -0700)
/proc/net/igmp walks IPv4 multicast memberships under RCU and
prints im->users without holding RTNL, while multicast join and leave
paths update the field while holding RTNL. 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: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260522093906.39764-1-sigefriedhyy@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/igmp.c

index 27d1201837793cd4dabf2fbd614828d3a800365e..f2aca659b29c93df3e43a2ee4d34243fcca0b97e 100644 (file)
@@ -1541,7 +1541,7 @@ static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
        }
 
        if  (im) {
-               im->users++;
+               WRITE_ONCE(im->users, im->users + 1);
                ip_mc_add_src(in_dev, &addr, mode, 0, NULL, 0);
                goto out;
        }
@@ -1550,7 +1550,7 @@ static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
        if (!im)
                goto out;
 
-       im->users = 1;
+       WRITE_ONCE(im->users, 1);
        im->interface = in_dev;
        in_dev_hold(in_dev);
        im->multiaddr = addr;
@@ -1784,7 +1784,10 @@ void __ip_mc_dec_group(struct in_device *in_dev, __be32 addr, gfp_t gfp)
             (i = rtnl_dereference(*ip)) != NULL;
             ip = &i->next_rcu) {
                if (i->multiaddr == addr) {
-                       if (--i->users == 0) {
+                       int new_users = i->users - 1;
+
+                       WRITE_ONCE(i->users, new_users);
+                       if (new_users == 0) {
                                ip_mc_hash_remove(in_dev, i);
                                *ip = i->next_rcu;
                                in_dev->mc_count--;
@@ -2977,7 +2980,7 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v)
                delta = im->timer.expires - jiffies;
                seq_printf(seq,
                           "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
-                          im->multiaddr, im->users,
+                          im->multiaddr, READ_ONCE(im->users),
                           im->tm_running,
                           im->tm_running ? jiffies_delta_to_clock_t(delta) : 0,
                           im->reporter);