diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-06-15 08:14:22 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-06-20 04:57:01 -0400 |
commit | 4f7eff10b20fc86f71f2db83e6b16cb5fbde8dbc (patch) | |
tree | d45f75665ceea2c56cc0b738ba4b0a099241aa84 /net/wireless | |
parent | 7fee4778bf56b0c5c86010d5b6f654177cc5da96 (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.c | 21 |
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 | ||
73 | static struct cfg80211_registered_device * | 73 | static 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 | */ |
139 | static struct cfg80211_registered_device * | 142 | static struct cfg80211_registered_device * |
140 | cfg80211_get_dev_from_info(struct genl_info *info) | 143 | cfg80211_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(); |