Re: [PATCH net] net: bridge: fix soft lockup in br_multicast_query_expired()

Nikolay Aleksandrov <[email protected]>
Newsgroups gmane.linux.network.bridge,gmane.linux.network,gmane.linux.kernel
Message-ID <[email protected]>
On 8/6/25 12:49, Wang Liang wrote:
> When set multicast_query_interval to a large value, the local variable
> 'time' in br_multicast_send_query() may overflow. If the time is smaller
> than jiffies, the timer will expire immediately, and then call mod_timer()
> again, which creates a loop and may trigger the following soft lockup
> issue:
> 
>   watchdog: BUG: soft lockup - CPU#1 stuck for 221s! [rb_consumer:66]
>   CPU: 1 UID: 0 PID: 66 Comm: rb_consumer Not tainted 6.16.0+ #259 PREEMPT(none)
>   Call Trace:
>    <IRQ>
>    __netdev_alloc_skb+0x2e/0x3a0
>    br_ip6_multicast_alloc_query+0x212/0x1b70
>    __br_multicast_send_query+0x376/0xac0
>    br_multicast_send_query+0x299/0x510
>    br_multicast_query_expired.constprop.0+0x16d/0x1b0
>    call_timer_fn+0x3b/0x2a0
>    __run_timers+0x619/0x950
>    run_timer_softirq+0x11c/0x220
>    handle_softirqs+0x18e/0x560
>    __irq_exit_rcu+0x158/0x1a0
>    sysvec_apic_timer_interrupt+0x76/0x90
>    </IRQ>
> 
> This issue can be reproduced with:
>   ip link add br0 type bridge
>   echo 1 > /sys/class/net/br0/bridge/multicast_querier
>   echo 0xffffffffffffffff >
>   	/sys/class/net/br0/bridge/multicast_query_interval
>   ip link set dev br0 up
> 
> Fix this by comparing expire time with jiffies, to avoid the timer loop.
> 
> Fixes: 7e4df51eb35d ("bridge: netlink: add support for igmp's intervals")
> Signed-off-by: Wang Liang <[email protected]>
> ---
>  net/bridge/br_multicast.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 1377f31b719c..631ae3b4c45d 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -1892,7 +1892,8 @@ static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
>  	time += own_query->startup_sent < brmctx->multicast_startup_query_count ?
>  		brmctx->multicast_startup_query_interval :
>  		brmctx->multicast_query_interval;
> -	mod_timer(&own_query->timer, time);
> +	if (time_is_after_jiffies(time))
> +		mod_timer(&own_query->timer, time);
>  }
>  
>  static void

This is the wrong way to fix it, it is a configuration issue, so we could either
cap the value at something that noone uses, e.g. 24 hours, or we could make sure time
is at least 1s (that is BR_MULTICAST_QUERY_INTVL_MIN).

The simple fix would be to do a min(time, BR_MULTICAST_QUERY_INTVL_MIN), but I'd go
for something similar to:
 commit 99b40610956a
 Author: Nikolay Aleksandrov <[email protected]>
 Date:   Mon Dec 27 19:21:15 2021 +0200

     net: bridge: mcast: add and enforce query interval minimum

for the maximum to avoid the overflow altogether. By the way multicast_startup_query_interval 
would also cause the same issue, so you'd have to cap it.

Cheers,
 Nik
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.