summaryrefslogtreecommitdiff
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-15 16:14:22 +0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-20 12:57:01 +0400
commit4f7eff10b20fc86f71f2db83e6b16cb5fbde8dbc (patch)
treed45f75665ceea2c56cc0b738ba4b0a099241aa84 /net/wireless
parent7fee4778bf56b0c5c86010d5b6f654177cc5da96 (diff)
downloadlinux-4f7eff10b20fc86f71f2db83e6b16cb5fbde8dbc.tar.xz
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,
}
static struct cfg80211_registered_device *
-__cfg80211_rdev_from_info(struct genl_info *info)
+__cfg80211_rdev_from_info(struct net *netns, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = NULL, *tmp;
struct net_device *netdev;
@@ -88,7 +88,7 @@ __cfg80211_rdev_from_info(struct genl_info *info)
if (info->attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
- netdev = dev_get_by_index(genl_info_net(info), ifindex);
+ netdev = dev_get_by_index(netns, ifindex);
if (netdev) {
if (netdev->ieee80211_ptr)
tmp = wiphy_to_dev(
@@ -110,10 +110,13 @@ __cfg80211_rdev_from_info(struct genl_info *info)
}
}
- if (rdev)
- return rdev;
+ if (!rdev)
+ return ERR_PTR(-ENODEV);
- return ERR_PTR(-ENODEV);
+ if (netns != wiphy_net(&rdev->wiphy))
+ return ERR_PTR(-ENODEV);
+
+ return rdev;
}
/*
@@ -137,12 +140,12 @@ __cfg80211_rdev_from_info(struct genl_info *info)
* be checked with IS_ERR() for errors.
*/
static struct cfg80211_registered_device *
-cfg80211_get_dev_from_info(struct genl_info *info)
+cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_rdev_from_info(info);
+ rdev = __cfg80211_rdev_from_info(netns, info);
/* if it is not an error we grab the lock on
* 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)
}
if (!netdev) {
- rdev = __cfg80211_rdev_from_info(info);
+ rdev = __cfg80211_rdev_from_info(genl_info_net(info), info);
if (IS_ERR(rdev)) {
mutex_unlock(&cfg80211_mutex);
return PTR_ERR(rdev);
@@ -6623,7 +6626,7 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
rtnl_lock();
if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
- rdev = cfg80211_get_dev_from_info(info);
+ rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
if (IS_ERR(rdev)) {
if (rtnl)
rtnl_unlock();