Skip to contentSkip to conversation

Patch "bonding: Fix bonding crash" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Sep 26, 2016

Subsystems (4)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

bonding: Fix bonding crash

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
bonding-fix-bonding-crash.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From foo@baz Wed Sep 21 12:45:10 CEST 2016

From: Mahesh Bandewar <[email protected]>
Date: Thu, 1 Sep 2016 22:18:34 -0700
Subject: bonding: Fix bonding crash

From: Mahesh Bandewar <[email protected]>

[ Upstream commit 24b27fc4cdf9e10c5e79e5923b6b7c2c5c95096c ]

Following few steps will crash kernel -

(a) Create bonding master
> modprobe bonding miimon=50
(b) Create macvlan bridge on eth2

      > ip link add link eth2 dev mvl0 address aa:0:0:0:0:01 \
	   type macvlan

(c) Now try adding eth2 into the bond
> echo +eth2 > /sys/class/net/bond0/bonding/slaves <crash>

Bonding does lots of things before checking if the device enslaved is busy or not.

In this case when the notifier call-chain sends notifications, the bond_netdev_event() assumes that the rx_handler /rx_handler_data is registered while the bond_enslave() hasn't progressed far enough to register rx_handler for the new slave.

This patch adds a rx_handler check that can be performed right at the beginning of the enslave code to avoid getting into this situation.

---
 drivers/net/bonding/bond_main.c |    7 ++++---
 include/linux/netdevice.h       |    1 +
 net/core/dev.c                  |   16 ++++++++++++++++
 3 files changed, 21 insertions(+), 3 deletions(-)
drivers/net/bonding/bond_main.c +4 -3
@@ -1317,9 +1317,10 @@ int bond_enslave(struct net_device *bond
 			    slave_dev->name);
 	}
 
-	/* already enslaved */
-	if (slave_dev->flags & IFF_SLAVE) {
-		netdev_dbg(bond_dev, "Error: Device was already enslaved\n");
+	/* already in-use? */
+	if (netdev_is_rx_handler_busy(slave_dev)) {
+		netdev_err(bond_dev,
+			   "Error: Device is in use and cannot be enslaved\n");
 		return -EBUSY;
 	}
 
include/linux/netdevice.h +1 -0
@@ -3036,6 +3036,7 @@ static inline void napi_free_frags(struc
 	napi->skb = NULL;
 }
 
+bool netdev_is_rx_handler_busy(struct net_device *dev);
 int netdev_rx_handler_register(struct net_device *dev,
 			       rx_handler_func_t *rx_handler,
 			       void *rx_handler_data);
net/core/dev.c +16 -0
@@ -3722,6 +3722,22 @@ static inline struct sk_buff *handle_ing
 }
 
 /**
+ *	netdev_is_rx_handler_busy - check if receive handler is registered
+ *	@dev: device to check
+ *
+ *	Check if a receive handler is already registered for a given device.
+ *	Return true if there one.
+ *
+ *	The caller must hold the rtnl_mutex.
+ */
+bool netdev_is_rx_handler_busy(struct net_device *dev)
+{
+	ASSERT_RTNL();
+	return dev && rtnl_dereference(dev->rx_handler);
+}
+EXPORT_SYMBOL_GPL(netdev_is_rx_handler_busy);
+
+/**
  *	netdev_rx_handler_register - register receive handler
  *	@dev: device to register a handler for
  *	@rx_handler: receive handler to register

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/bonding-fix-bonding-crash.patch