• Joseph Huang's avatar
    bridge: Fix a deadlock when enabling multicast snooping · 851d0a73
    Joseph Huang authored
    When enabling multicast snooping, bridge module deadlocks on multicast_lock
    if 1) IPv6 is enabled, and 2) there is an existing querier on the same L2
    network.
    
    The deadlock was caused by the following sequence: While holding the lock,
    br_multicast_open calls br_multicast_join_snoopers, which eventually causes
    IP stack to (attempt to) send out a Listener Report (in igmp6_join_group).
    Since the destination Ethernet address is a multicast address, br_dev_xmit
    feeds the packet back to the bridge via br_multicast_rcv, which in turn
    calls br_multicast_add_group, which then deadlocks on multicast_lock.
    
    The fix is to move the call br_multicast_join_snoopers outside of the
    critical section. This works since br_multicast_join_snoopers only deals
    with IP and does not modify any multicast data structures of the bridge,
    so there's no need to hold the lock.
    
    Steps to reproduce:
    1. sysctl net.ipv6.conf.all.force_mld_version=1
    2. have another querier
    3. ip link set dev bridge type bridge mcast_snooping 0 && \
       ip link set dev bridge type bridge mcast_snooping 1 < deadlock >
    
    A typical call trace looks like the following:
    
    [  936.251495]  _raw_spin_lock+0x5c/0x68
    [  936.255221]  br_multicast_add_group+0x40/0x170 [bridge]
    [  936.260491]  br_multicast_rcv+0x7ac/0xe30 [bridge]
    [  936.265322]  br_dev_xmit+0x140/0x368 [bridge]
    [  936.269689]  dev_hard_start_xmit+0x94/0x158
    [  936.273876]  __dev_queue_xmit+0x5ac/0x7f8
    [  936.277890]  dev_queue_xmit+0x10/0x18
    [  936.281563]  neigh_resolve_output+0xec/0x198
    [  936.285845]  ip6_finish_output2+0x240/0x710
    [  936.290039]  __ip6_finish_output+0x130/0x170
    [  936.294318]  ip6_output+0x6c/0x1c8
    [  936.297731]  NF_HOOK.constprop.0+0xd8/0xe8
    [  936.301834]  igmp6_send+0x358/0x558
    [  936.305326]  igmp6_join_group.part.0+0x30/0xf0
    [  936.309774]  igmp6_group_added+0xfc/0x110
    [  936.313787]  __ipv6_dev_mc_inc+0x1a4/0x290
    [  936.317885]  ipv6_dev_mc_inc+0x10/0x18
    [  936.321677]  br_multicast_open+0xbc/0x110 [bridge]
    [  936.326506]  br_multicast_toggle+0xec/0x140 [bridge]
    
    Fixes: 4effd28c ("bridge: join all-snoopers multicast address")
    Signed-off-by: default avatarJoseph Huang <Joseph.Huang@garmin.com>
    Acked-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
    Link: https://lore.kernel.org/r/20201204235628.50653-1-Joseph.Huang@garmin.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    851d0a73
br_private.h 43.5 KB