--- /dev/null
+From foo@baz Wed Sep 21 12:45:10 CEST 2016
+From: Mahesh Bandewar <maheshb@google.com>
+Date: Thu, 1 Sep 2016 22:18:34 -0700
+Subject: bonding: Fix bonding crash
+
+From: Mahesh Bandewar <maheshb@google.com>
+
+
+[ 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.
+
+Signed-off-by: Mahesh Bandewar <maheshb@google.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/bonding/bond_main.c | 7 ++++---
+ include/linux/netdevice.h | 1 +
+ net/core/dev.c | 16 ++++++++++++++++
+ 3 files changed, 21 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -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;
+ }
+
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -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);
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -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