lkml.org 
[lkml]   [2013]   [Oct]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 041/135] bonding: Fix broken promiscuity reference counting issue
    Date
    3.11-stable review patch.  If anyone has any objections, please let me know.

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

    From: Neil Horman <nhorman@tuxdriver.com>

    [ Upstream commit 5a0068deb611109c5ba77358be533f763f395ee4 ]

    Recently grabbed this report:
    https://bugzilla.redhat.com/show_bug.cgi?id=1005567

    Of an issue in which the bonding driver, with an attached vlan encountered the
    following errors when bond0 was taken down and back up:

    dummy1: promiscuity touches roof, set promiscuity failed. promiscuity feature of
    device might be broken.

    The error occurs because, during __bond_release_one, if we release our last
    slave, we take on a random mac address and issue a NETDEV_CHANGEADDR
    notification. With an attached vlan, the vlan may see that the vlan and bond
    mac address were in sync, but no longer are. This triggers a call to dev_uc_add
    and dev_set_rx_mode, which enables IFF_PROMISC on the bond device. Then, when
    we complete __bond_release_one, we use the current state of the bond flags to
    determine if we should decrement the promiscuity of the releasing slave. But
    since the bond changed promiscuity state during the release operation, we
    incorrectly decrement the slave promisc count when it wasn't in promiscuous mode
    to begin with, causing the above error

    Fix is pretty simple, just cache the bonding flags at the start of the function
    and use those when determining the need to set promiscuity.

    This is also needed for the ALLMULTI flag

    Reported-by: Mark Wu <wudxw@linux.vnet.ibm.com>
    CC: Jay Vosburgh <fubar@us.ibm.com>
    CC: Andy Gospodarek <andy@greyhouse.net>
    CC: Mark Wu <wudxw@linux.vnet.ibm.com>
    CC: "David S. Miller" <davem@davemloft.net>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/net/bonding/bond_main.c | 13 ++++++++++---
    1 file changed, 10 insertions(+), 3 deletions(-)

    --- a/drivers/net/bonding/bond_main.c
    +++ b/drivers/net/bonding/bond_main.c
    @@ -1947,6 +1947,7 @@ static int __bond_release_one(struct net
    struct bonding *bond = netdev_priv(bond_dev);
    struct slave *slave, *oldcurrent;
    struct sockaddr addr;
    + int old_flags = bond_dev->flags;
    netdev_features_t old_features = bond_dev->features;

    /* slave is not a slave or master is not master of this slave */
    @@ -2077,12 +2078,18 @@ static int __bond_release_one(struct net
    * bond_change_active_slave(..., NULL)
    */
    if (!USES_PRIMARY(bond->params.mode)) {
    - /* unset promiscuity level from slave */
    - if (bond_dev->flags & IFF_PROMISC)
    + /* unset promiscuity level from slave
    + * NOTE: The NETDEV_CHANGEADDR call above may change the value
    + * of the IFF_PROMISC flag in the bond_dev, but we need the
    + * value of that flag before that change, as that was the value
    + * when this slave was attached, so we cache at the start of the
    + * function and use it here. Same goes for ALLMULTI below
    + */
    + if (old_flags & IFF_PROMISC)
    dev_set_promiscuity(slave_dev, -1);

    /* unset allmulti level from slave */
    - if (bond_dev->flags & IFF_ALLMULTI)
    + if (old_flags & IFF_ALLMULTI)
    dev_set_allmulti(slave_dev, -1);

    bond_hw_addr_flush(bond_dev, slave_dev);



    \
     
     \ /
      Last update: 2013-10-12 00:01    [W:2.777 / U:0.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site