Commit 761cf7ec authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville
Browse files

cfg80211: add assert_cfg80211_lock() to ensure proper protection


Signed-off-by: default avatarLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent bcf4f99b
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
...@@ -50,6 +49,8 @@ cfg80211_drv_by_wiphy_idx(int wiphy_idx) ...@@ -50,6 +49,8 @@ cfg80211_drv_by_wiphy_idx(int wiphy_idx)
if (!wiphy_idx_valid(wiphy_idx)) if (!wiphy_idx_valid(wiphy_idx))
return NULL; return NULL;
assert_cfg80211_lock();
list_for_each_entry(drv, &cfg80211_drv_list, list) { list_for_each_entry(drv, &cfg80211_drv_list, list) {
if (drv->wiphy_idx == wiphy_idx) { if (drv->wiphy_idx == wiphy_idx) {
result = drv; result = drv;
...@@ -69,6 +70,8 @@ __cfg80211_drv_from_info(struct genl_info *info) ...@@ -69,6 +70,8 @@ __cfg80211_drv_from_info(struct genl_info *info)
struct net_device *dev; struct net_device *dev;
int err = -EINVAL; int err = -EINVAL;
assert_cfg80211_lock();
if (info->attrs[NL80211_ATTR_WIPHY]) { if (info->attrs[NL80211_ATTR_WIPHY]) {
bywiphyidx = cfg80211_drv_by_wiphy_idx( bywiphyidx = cfg80211_drv_by_wiphy_idx(
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY])); nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <linux/mutex.h>
#include <net/genetlink.h> #include <net/genetlink.h>
#include <net/wireless.h> #include <net/wireless.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>
...@@ -73,6 +74,11 @@ bool wiphy_idx_valid(int wiphy_idx) ...@@ -73,6 +74,11 @@ bool wiphy_idx_valid(int wiphy_idx)
extern struct mutex cfg80211_mutex; extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_drv_list; extern struct list_head cfg80211_drv_list;
static inline void assert_cfg80211_lock(void)
{
BUG_ON(!mutex_is_locked(&cfg80211_mutex));
}
struct cfg80211_internal_bss { struct cfg80211_internal_bss {
struct list_head list; struct list_head list;
struct rb_node rbn; struct rb_node rbn;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/ieee80211.h> #include <linux/ieee80211.h>
...@@ -138,6 +137,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, ...@@ -138,6 +137,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
int i; int i;
u16 ifmodes = dev->wiphy.interface_modes; u16 ifmodes = dev->wiphy.interface_modes;
assert_cfg80211_lock();
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
if (!hdr) if (!hdr)
return -1; return -1;
......
...@@ -276,6 +276,8 @@ static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) ...@@ -276,6 +276,8 @@ static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y)
static bool regdom_changed(const char *alpha2) static bool regdom_changed(const char *alpha2)
{ {
assert_cfg80211_lock();
if (!cfg80211_regdomain) if (!cfg80211_regdomain)
return true; return true;
if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
...@@ -830,6 +832,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, ...@@ -830,6 +832,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
assert_cfg80211_lock();
sband = wiphy->bands[band]; sband = wiphy->bands[band];
BUG_ON(chan_idx >= sband->n_channels); BUG_ON(chan_idx >= sband->n_channels);
chan = &sband->channels[chan_idx]; chan = &sband->channels[chan_idx];
...@@ -1042,6 +1046,9 @@ static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, ...@@ -1042,6 +1046,9 @@ static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
const char *alpha2) const char *alpha2)
{ {
assert_cfg80211_lock();
/* All initial requests are respected */ /* All initial requests are respected */
if (!last_request) if (!last_request)
return 0; return 0;
...@@ -1122,6 +1129,8 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, ...@@ -1122,6 +1129,8 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
bool intersect = false; bool intersect = false;
int r = 0; int r = 0;
assert_cfg80211_lock();
r = ignore_request(wiphy, set_by, alpha2); r = ignore_request(wiphy, set_by, alpha2);
if (r == REG_INTERSECT) { if (r == REG_INTERSECT) {
...@@ -1217,6 +1226,8 @@ EXPORT_SYMBOL(regulatory_hint); ...@@ -1217,6 +1226,8 @@ EXPORT_SYMBOL(regulatory_hint);
static bool reg_same_country_ie_hint(struct wiphy *wiphy, static bool reg_same_country_ie_hint(struct wiphy *wiphy,
u32 country_ie_checksum) u32 country_ie_checksum)
{ {
assert_cfg80211_lock();
if (!last_request->wiphy) if (!last_request->wiphy)
return false; return false;
if (likely(last_request->wiphy != wiphy)) if (likely(last_request->wiphy != wiphy))
...@@ -1583,6 +1594,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) ...@@ -1583,6 +1594,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
{ {
int r; int r;
assert_cfg80211_lock();
/* Note that this doesn't update the wiphys, this is done below */ /* Note that this doesn't update the wiphys, this is done below */
r = __set_regdom(rd); r = __set_regdom(rd);
if (r) { if (r) {
...@@ -1605,6 +1618,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) ...@@ -1605,6 +1618,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
/* Caller must hold cfg80211_mutex */ /* Caller must hold cfg80211_mutex */
void reg_device_remove(struct wiphy *wiphy) void reg_device_remove(struct wiphy *wiphy)
{ {
assert_cfg80211_lock();
kfree(wiphy->regd); kfree(wiphy->regd);
if (!last_request || !last_request->wiphy) if (!last_request || !last_request->wiphy)
return; return;
......
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