mac802154: allow only one WPAN to be up at any given time
authorPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Mon, 31 Mar 2014 19:37:45 +0000 (21:37 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 1 Apr 2014 20:25:51 +0000 (16:25 -0400)
All 802.15.4 PHY devices with drivers in tree can support only one WPAN
at any given time, yet the stack allows arbitrarily many WPAN devices to
be created and up at the same time. This cannot work with what the
hardware provides, and in the current implementation, provides an easy
DoS vector to any process on the system that may call socket() and
sendmsg().

Thus, allow only one WPAN per PHY to be up at once, just like mac80211
does for managed devices.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/mac802154/ieee802154_dev.c
net/mac802154/mac802154.h

index 10cdb091b775602a1807816256a22f734c0dfb8e..e7aa76445fe1501698984e1666d048f4d900d17d 100644 (file)
 int mac802154_slave_open(struct net_device *dev)
 {
        struct mac802154_sub_if_data *priv = netdev_priv(dev);
+       struct mac802154_sub_if_data *subif;
        struct mac802154_priv *ipriv = priv->hw;
        int res = 0;
 
+       ASSERT_RTNL();
+
+       if (priv->type == IEEE802154_DEV_WPAN) {
+               mutex_lock(&priv->hw->slaves_mtx);
+               list_for_each_entry(subif, &priv->hw->slaves, list) {
+                       if (subif != priv && subif->type == priv->type &&
+                           subif->running) {
+                               mutex_unlock(&priv->hw->slaves_mtx);
+                               return -EBUSY;
+                       }
+               }
+               mutex_unlock(&priv->hw->slaves_mtx);
+       }
+
+       mutex_lock(&priv->hw->slaves_mtx);
+       priv->running = true;
+       mutex_unlock(&priv->hw->slaves_mtx);
+
        if (ipriv->open_count++ == 0) {
                res = ipriv->ops->start(&ipriv->hw);
                WARN_ON(res);
@@ -69,8 +88,14 @@ int mac802154_slave_close(struct net_device *dev)
        struct mac802154_sub_if_data *priv = netdev_priv(dev);
        struct mac802154_priv *ipriv = priv->hw;
 
+       ASSERT_RTNL();
+
        netif_stop_queue(dev);
 
+       mutex_lock(&priv->hw->slaves_mtx);
+       priv->running = false;
+       mutex_unlock(&priv->hw->slaves_mtx);
+
        if (!--ipriv->open_count)
                ipriv->ops->stop(&ipriv->hw);
 
index 4619486f1da21e728b609f94d785ce683426ccdf..f40522ef288c76c8f5b22eb8c34b7ca501d264d2 100644 (file)
@@ -71,6 +71,7 @@ struct mac802154_sub_if_data {
        struct net_device *dev;
 
        int type;
+       bool running;
 
        spinlock_t mib_lock;