team: fix possible recursive locking when add slaves [Linux 3.16.72]

This Linux kernel change "team: fix possible recursive locking when add slaves" is included in the Linux 3.16.72 release. This change is authored by Hangbin Liu <liuhangbin [at] gmail.com> on Fri Apr 19 14:31:00 2019 +0800. The commit for this change in Linux stable tree is 3b2cfca (patch) which is from upstream commit 925b0c8. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 925b0c8.

team: fix possible recursive locking when add slaves

commit 925b0c841e066b488cc3a60272472b2c56300704 upstream.

If we add a bond device which is already the master of the team interface,
we will hold the team->lock in team_add_slave() first and then request the
lock in team_set_mac_address() again. The functions are called like:

- team_add_slave()
 - team_port_add()
   - team_port_enter()
     - team_modeop_port_enter()
       - __set_port_dev_addr()
         - dev_set_mac_address()
           - bond_set_mac_address()
             - dev_set_mac_address()
           - team_set_mac_address

Although team_upper_dev_link() would check the upper devices but it is
called too late. Fix it by adding a checking before processing the slave.

v2: Do not split the string in netdev_err()

Fixes: 3d249d4ca7d0 ("net: introduce ethernet teaming device")
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: netlink doesn't support extack]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

There are 6 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/team/team.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index d651104..8d408cd 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1116,6 +1116,12 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
        return -EINVAL;
    }

+   if (netdev_has_upper_dev(dev, port_dev)) {
+       netdev_err(dev, "Device %s is already an upper device of the team interface\n",
+              portname);
+       return -EBUSY;
+   }
+
    if (port_dev->features & NETIF_F_VLAN_CHALLENGED &&
        vlan_uses_dev(dev)) {
        netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n",

Leave a Reply

Your email address will not be published. Required fields are marked *