Commit 4f7eff10 authored by Johannes Berg's avatar Johannes Berg

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: default avatarJohannes Berg <johannes.berg@intel.com>
parent 7fee4778
...@@ -71,7 +71,7 @@ static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs, ...@@ -71,7 +71,7 @@ static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
} }
static struct cfg80211_registered_device * 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 cfg80211_registered_device *rdev = NULL, *tmp;
struct net_device *netdev; struct net_device *netdev;
...@@ -88,7 +88,7 @@ __cfg80211_rdev_from_info(struct genl_info *info) ...@@ -88,7 +88,7 @@ __cfg80211_rdev_from_info(struct genl_info *info)
if (info->attrs[NL80211_ATTR_IFINDEX]) { if (info->attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(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) {
if (netdev->ieee80211_ptr) if (netdev->ieee80211_ptr)
tmp = wiphy_to_dev( tmp = wiphy_to_dev(
...@@ -110,10 +110,13 @@ __cfg80211_rdev_from_info(struct genl_info *info) ...@@ -110,10 +110,13 @@ __cfg80211_rdev_from_info(struct genl_info *info)
} }
} }
if (rdev) if (!rdev)
return 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) ...@@ -137,12 +140,12 @@ __cfg80211_rdev_from_info(struct genl_info *info)
* be checked with IS_ERR() for errors. * be checked with IS_ERR() for errors.
*/ */
static struct cfg80211_registered_device * 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; struct cfg80211_registered_device *rdev;
mutex_lock(&cfg80211_mutex); 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 /* if it is not an error we grab the lock on
* it to assure it won't be going away while * 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,7 +1422,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
} }
if (!netdev) { if (!netdev) {
rdev = __cfg80211_rdev_from_info(info); rdev = __cfg80211_rdev_from_info(genl_info_net(info), info);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
mutex_unlock(&cfg80211_mutex); mutex_unlock(&cfg80211_mutex);
return PTR_ERR(rdev); return PTR_ERR(rdev);
...@@ -6623,7 +6626,7 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, ...@@ -6623,7 +6626,7 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
rtnl_lock(); rtnl_lock();
if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { 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 (IS_ERR(rdev)) {
if (rtnl) if (rtnl)
rtnl_unlock(); rtnl_unlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment