net/ipv4/igmp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
/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().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
---
Changes in v2:
- Added Fixes: tag
net/ipv4/igmp.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 27d120183779..f2aca659b29c 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -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);
--
2.43.0
On Fri, May 22, 2026 at 06:39:06PM +0900, Yuyang Huang wrote:
> /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().
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
> Changes in v2:
> - Added Fixes: tag
>
> net/ipv4/igmp.c | 11 +++++++----
> 1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
> index 27d120183779..f2aca659b29c 100644
> --- a/net/ipv4/igmp.c
> +++ b/net/ipv4/igmp.c
> @@ -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);
This one isn't necessary since the object was just allocated and not yet
published
>This one isn't necessary since the object was just allocated and not yet
>published
Thanks for the comment. I did consider not modifying it when writing
the patch, but decided to keep it for consistency, it makes the code
easier to reason about later. If you feel strongly about removing it,
I'm happy to send a v3.
On Sun, May 24, 2026 at 10:59 PM Ido Schimmel <idosch@nvidia.com> wrote:
>
> On Fri, May 22, 2026 at 06:39:06PM +0900, Yuyang Huang wrote:
> > /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().
> >
> > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> > Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
>
> > ---
> > Changes in v2:
> > - Added Fixes: tag
> >
> > net/ipv4/igmp.c | 11 +++++++----
> > 1 file changed, 7 insertions(+), 4 deletions(-)
> >
> > diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
> > index 27d120183779..f2aca659b29c 100644
> > --- a/net/ipv4/igmp.c
> > +++ b/net/ipv4/igmp.c
> > @@ -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);
>
> This one isn't necessary since the object was just allocated and not yet
> published
On 5/22/26 5:39 PM, Yuyang Huang wrote:
> /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().
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
On Fri, May 22, 2026 at 3:38 AM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
>
> On 5/22/26 5:39 PM, Yuyang Huang wrote:
> > /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().
> >
> > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> > Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
>
>
> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Eric Dumazet <edumazet@google.com>
© 2016 - 2026 Red Hat, Inc.