macvlan: fix allmulti reference counting in passthru mode

Enabling allmulticast on a down passthru macvlan, bringing it up,
then toggling allmulticast off and on can underflow the lower device's
allmulti reference count.

macvlan_change_rx_flags() only propagates IFF_ALLMULTI changes while
the macvlan is up. However, the passthru path in macvlan_open() skips
taking an allmulti reference when IFF_ALLMULTI is already set.
Clearing allmulticast after opening the device therefore decrements
a reference that was never taken. With no other allmulti users, the
unsigned counter wraps from zero to UINT_MAX. The next increment
fails with -EOVERFLOW and reports "allmulti touches roof".

The issue was observed during development testing with 5.10 and 6.12
kernels. It was reproduced on Linux 6.12.68 by enabling allmulticast
on a down passthru macvlan, bringing it up, and toggling allmulticast
off and on. This triggered the “allmulti touches roof” warning.

Signed-off-by: Prasad Koya <prasad@arista.com>
Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
This commit is contained in:
Prasad Koya 2026-10-26 19:46:35 -07:00 committed by Dave Miller
parent 66dfb2cacd
commit d8a4f4c59d

View File

@ -643,6 +643,14 @@ static int macvlan_open(struct net_device *dev)
if (err < 0)
goto out;
}
if (dev->flags & IFF_ALLMULTI) {
err = dev_set_allmulti(lowerdev, 1);
if (err < 0) {
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
dev_set_promiscuity(lowerdev, -1);
goto out;
}
}
goto hash_add;
}
@ -713,6 +721,8 @@ static int macvlan_stop(struct net_device *dev)
dev_mc_unsync(lowerdev, dev);
if (macvlan_passthru(vlan->port)) {
if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(lowerdev, -1);
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
dev_set_promiscuity(lowerdev, -1);
goto hash_del;