lkml.org 
[lkml]   [2016]   [Jan]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.1 083/127] bridge: fix lockdep addr_list_lock false positive splat
    Date
    4.1-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

    [ Upstream commit c6894dec8ea9ae05747124dce98b3b5c2e69b168 ]

    After promisc mode management was introduced a bridge device could do
    dev_set_promiscuity from its ndo_change_rx_flags() callback which in
    turn can be called after the bridge's addr_list_lock has been taken
    (e.g. by dev_uc_add). This causes a false positive lockdep splat because
    the port interfaces' addr_list_lock is taken when br_manage_promisc()
    runs after the bridge's addr list lock was already taken.
    To remove the false positive introduce a custom bridge addr_list_lock
    class and set it on bridge init.
    A simple way to reproduce this is with the following:
    $ brctl addbr br0
    $ ip l add l br0 br0.100 type vlan id 100
    $ ip l set br0 up
    $ ip l set br0.100 up
    $ echo 1 > /sys/class/net/br0/bridge/vlan_filtering
    $ brctl addif br0 eth0
    Splat:
    [ 43.684325] =============================================
    [ 43.684485] [ INFO: possible recursive locking detected ]
    [ 43.684636] 4.4.0-rc8+ #54 Not tainted
    [ 43.684755] ---------------------------------------------
    [ 43.684906] brctl/1187 is trying to acquire lock:
    [ 43.685047] (_xmit_ETHER){+.....}, at: [<ffffffff8150169e>] dev_set_rx_mode+0x1e/0x40
    [ 43.685460] but task is already holding lock:
    [ 43.685618] (_xmit_ETHER){+.....}, at: [<ffffffff815072a7>] dev_uc_add+0x27/0x80
    [ 43.686015] other info that might help us debug this:
    [ 43.686316] Possible unsafe locking scenario:

    [ 43.686743] CPU0
    [ 43.686967] ----
    [ 43.687197] lock(_xmit_ETHER);
    [ 43.687544] lock(_xmit_ETHER);
    [ 43.687886] *** DEADLOCK ***

    [ 43.688438] May be due to missing lock nesting notation

    [ 43.688882] 2 locks held by brctl/1187:
    [ 43.689134] #0: (rtnl_mutex){+.+.+.}, at: [<ffffffff81510317>] rtnl_lock+0x17/0x20
    [ 43.689852] #1: (_xmit_ETHER){+.....}, at: [<ffffffff815072a7>] dev_uc_add+0x27/0x80
    [ 43.690575] stack backtrace:
    [ 43.690970] CPU: 0 PID: 1187 Comm: brctl Not tainted 4.4.0-rc8+ #54
    [ 43.691270] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.1-20150318_183358- 04/01/2014
    [ 43.691770] ffffffff826a25c0 ffff8800369fb8e0 ffffffff81360ceb ffffffff826a25c0
    [ 43.692425] ffff8800369fb9b8 ffffffff810d0466 ffff8800369fb968 ffffffff81537139
    [ 43.693071] ffff88003a08c880 0000000000000000 00000000ffffffff 0000000002080020
    [ 43.693709] Call Trace:
    [ 43.693931] [<ffffffff81360ceb>] dump_stack+0x4b/0x70
    [ 43.694199] [<ffffffff810d0466>] __lock_acquire+0x1e46/0x1e90
    [ 43.694483] [<ffffffff81537139>] ? netlink_broadcast_filtered+0x139/0x3e0
    [ 43.694789] [<ffffffff8153b5da>] ? nlmsg_notify+0x5a/0xc0
    [ 43.695064] [<ffffffff810d10f5>] lock_acquire+0xe5/0x1f0
    [ 43.695340] [<ffffffff8150169e>] ? dev_set_rx_mode+0x1e/0x40
    [ 43.695623] [<ffffffff815edea5>] _raw_spin_lock_bh+0x45/0x80
    [ 43.695901] [<ffffffff8150169e>] ? dev_set_rx_mode+0x1e/0x40
    [ 43.696180] [<ffffffff8150169e>] dev_set_rx_mode+0x1e/0x40
    [ 43.696460] [<ffffffff8150189c>] dev_set_promiscuity+0x3c/0x50
    [ 43.696750] [<ffffffffa0586845>] br_port_set_promisc+0x25/0x50 [bridge]
    [ 43.697052] [<ffffffffa05869aa>] br_manage_promisc+0x8a/0xe0 [bridge]
    [ 43.697348] [<ffffffffa05826ee>] br_dev_change_rx_flags+0x1e/0x20 [bridge]
    [ 43.697655] [<ffffffff81501532>] __dev_set_promiscuity+0x132/0x1f0
    [ 43.697943] [<ffffffff81501672>] __dev_set_rx_mode+0x82/0x90
    [ 43.698223] [<ffffffff815072de>] dev_uc_add+0x5e/0x80
    [ 43.698498] [<ffffffffa05b3c62>] vlan_device_event+0x542/0x650 [8021q]
    [ 43.698798] [<ffffffff8109886d>] notifier_call_chain+0x5d/0x80
    [ 43.699083] [<ffffffff810988b6>] raw_notifier_call_chain+0x16/0x20
    [ 43.699374] [<ffffffff814f456e>] call_netdevice_notifiers_info+0x6e/0x80
    [ 43.699678] [<ffffffff814f4596>] call_netdevice_notifiers+0x16/0x20
    [ 43.699973] [<ffffffffa05872be>] br_add_if+0x47e/0x4c0 [bridge]
    [ 43.700259] [<ffffffffa058801e>] add_del_if+0x6e/0x80 [bridge]
    [ 43.700548] [<ffffffffa0588b5f>] br_dev_ioctl+0xaf/0xc0 [bridge]
    [ 43.700836] [<ffffffff8151a7ac>] dev_ifsioc+0x30c/0x3c0
    [ 43.701106] [<ffffffff8151aac9>] dev_ioctl+0xf9/0x6f0
    [ 43.701379] [<ffffffff81254345>] ? mntput_no_expire+0x5/0x450
    [ 43.701665] [<ffffffff812543ee>] ? mntput_no_expire+0xae/0x450
    [ 43.701947] [<ffffffff814d7b02>] sock_do_ioctl+0x42/0x50
    [ 43.702219] [<ffffffff814d8175>] sock_ioctl+0x1e5/0x290
    [ 43.702500] [<ffffffff81242d0b>] do_vfs_ioctl+0x2cb/0x5c0
    [ 43.702771] [<ffffffff81243079>] SyS_ioctl+0x79/0x90
    [ 43.703033] [<ffffffff815eebb6>] entry_SYSCALL_64_fastpath+0x16/0x7a

    CC: Vlad Yasevich <vyasevic@redhat.com>
    CC: Stephen Hemminger <stephen@networkplumber.org>
    CC: Bridge list <bridge@lists.linux-foundation.org>
    CC: Andy Gospodarek <gospo@cumulusnetworks.com>
    CC: Roopa Prabhu <roopa@cumulusnetworks.com>
    Fixes: 2796d0c648c9 ("bridge: Automatically manage port promiscuous mode.")
    Reported-by: Andy Gospodarek <gospo@cumulusnetworks.com>
    Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/bridge/br_device.c | 8 ++++++++
    1 file changed, 8 insertions(+)

    --- a/net/bridge/br_device.c
    +++ b/net/bridge/br_device.c
    @@ -28,6 +28,8 @@
    const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
    EXPORT_SYMBOL_GPL(nf_br_ops);

    +static struct lock_class_key bridge_netdev_addr_lock_key;
    +
    /* net device transmit always called with BH disabled */
    netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
    {
    @@ -87,6 +89,11 @@ out:
    return NETDEV_TX_OK;
    }

    +static void br_set_lockdep_class(struct net_device *dev)
    +{
    + lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key);
    +}
    +
    static int br_dev_init(struct net_device *dev)
    {
    struct net_bridge *br = netdev_priv(dev);
    @@ -99,6 +106,7 @@ static int br_dev_init(struct net_device
    err = br_vlan_init(br);
    if (err)
    free_percpu(br->stats);
    + br_set_lockdep_class(dev);

    return err;
    }

    \
     
     \ /
      Last update: 2016-01-27 20:41    [W:4.210 / U:0.400 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site