summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>2014-03-31 21:37:45 +0200
committerDavid S. Miller <davem@davemloft.net>2014-04-01 16:25:51 -0400
commit336908f6d73ca297bd46948eb5d04d2020a88606 (patch)
tree9240a0e5acf234c77211c173e626d22f55bd1467
parent01d32f6e5a3f709a90aadbb73723e77a96d67cb2 (diff)
downloadlinux-stable-336908f6d73ca297bd46948eb5d04d2020a88606.tar.gz
linux-stable-336908f6d73ca297bd46948eb5d04d2020a88606.tar.bz2
linux-stable-336908f6d73ca297bd46948eb5d04d2020a88606.zip
mac802154: allow only one WPAN to be up at any given time
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>
-rw-r--r--net/mac802154/ieee802154_dev.c25
-rw-r--r--net/mac802154/mac802154.h1
2 files changed, 26 insertions, 0 deletions
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 10cdb091b775..e7aa76445fe1 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -36,9 +36,28 @@
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);
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
index 4619486f1da2..f40522ef288c 100644
--- a/net/mac802154/mac802154.h
+++ b/net/mac802154/mac802154.h
@@ -71,6 +71,7 @@ struct mac802154_sub_if_data {
struct net_device *dev;
int type;
+ bool running;
spinlock_t mib_lock;