aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-15 08:14:22 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-20 04:57:01 -0400
commit4f7eff10b20fc86f71f2db83e6b16cb5fbde8dbc (patch)
treed45f75665ceea2c56cc0b738ba4b0a099241aa84 /net/wireless
parent7fee4778bf56b0c5c86010d5b6f654177cc5da96 (diff)
nl80211: fix netns separation
There are currently a few ways to "escape" the network namespace and access a wiphy that belongs to another namespace. Add a netns argument to the relevant functions to fix this. One remaining issue with testmode will be fixed in a follow-up patch. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0ec9779c2b56..af232912fff8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -71,7 +71,7 @@ static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
71} 71}
72 72
73static struct cfg80211_registered_device * 73static struct cfg80211_registered_device *
74__cfg80211_rdev_from_info(struct genl_info *info) 74__cfg80211_rdev_from_info(struct net *netns, struct genl_info *info)
75{ 75{
76 struct cfg80211_registered_device *rdev = NULL, *tmp; 76 struct cfg80211_registered_device *rdev = NULL, *tmp;
77 struct net_device *netdev; 77 struct net_device *netdev;
@@ -88,7 +88,7 @@ __cfg80211_rdev_from_info(struct genl_info *info)
88 88
89 if (info->attrs[NL80211_ATTR_IFINDEX]) { 89 if (info->attrs[NL80211_ATTR_IFINDEX]) {
90 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); 90 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
91 netdev = dev_get_by_index(genl_info_net(info), ifindex); 91 netdev = dev_get_by_index(netns, ifindex);
92 if (netdev) { 92 if (netdev) {
93 if (netdev->ieee80211_ptr) 93 if (netdev->ieee80211_ptr)
94 tmp = wiphy_to_dev( 94 tmp = wiphy_to_dev(
@@ -110,10 +110,13 @@ __cfg80211_rdev_from_info(struct genl_info *info)
110 } 110 }
111 } 111 }
112 112
113 if (rdev) 113 if (!rdev)
114 return rdev; 114 return ERR_PTR(-ENODEV);
115 115
116 return ERR_PTR(-ENODEV); 116 if (netns != wiphy_net(&rdev->wiphy))
117 return ERR_PTR(-ENODEV);
118
119 return rdev;
117} 120}
118 121
119/* 122/*
@@ -137,12 +140,12 @@ __cfg80211_rdev_from_info(struct genl_info *info)
137 * be checked with IS_ERR() for errors. 140 * be checked with IS_ERR() for errors.
138 */ 141 */
139static struct cfg80211_registered_device * 142static struct cfg80211_registered_device *
140cfg80211_get_dev_from_info(struct genl_info *info) 143cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
141{ 144{
142 struct cfg80211_registered_device *rdev; 145 struct cfg80211_registered_device *rdev;
143 146
144 mutex_lock(&cfg80211_mutex); 147 mutex_lock(&cfg80211_mutex);
145 rdev = __cfg80211_rdev_from_info(info); 148 rdev = __cfg80211_rdev_from_info(netns, info);
146 149
147 /* if it is not an error we grab the lock on 150 /* if it is not an error we grab the lock on
148 * it to assure it won't be going away while 151 * it to assure it won't be going away while
@@ -1419,7 +1422,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1419 } 1422 }
1420 1423
1421 if (!netdev) { 1424 if (!netdev) {
1422 rdev = __cfg80211_rdev_from_info(info); 1425 rdev = __cfg80211_rdev_from_info(genl_info_net(info), info);
1423 if (IS_ERR(rdev)) { 1426 if (IS_ERR(rdev)) {
1424 mutex_unlock(&cfg80211_mutex); 1427 mutex_unlock(&cfg80211_mutex);
1425 return PTR_ERR(rdev); 1428 return PTR_ERR(rdev);
@@ -6623,7 +6626,7 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
6623 rtnl_lock(); 6626 rtnl_lock();
6624 6627
6625 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { 6628 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
6626 rdev = cfg80211_get_dev_from_info(info); 6629 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
6627 if (IS_ERR(rdev)) { 6630 if (IS_ERR(rdev)) {
6628 if (rtnl) 6631 if (rtnl)
6629 rtnl_unlock(); 6632 rtnl_unlock();