The function wiphy_update_regulatory() uses the static variable last_request and thus needs to be called with reg_mutex held. This is the case for all users in reg.c, but the function was exported for use by wiphy_register(), from where it is called without the lock being held. Fix this by making wiphy_update_regulatory() private and introducing regulatory_update() as a wrapper that acquires and holds the lock. Signed-off-by: Sven Neumann <s.neumann@xxxxxxxxxxxx> --- net/wireless/core.c | 2 +- net/wireless/core.h | 2 - net/wireless/reg.c | 62 +++++++++++++++++++++++++++++--------------------- net/wireless/reg.h | 2 + 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index c22ef34..179921e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -577,7 +577,7 @@ int wiphy_register(struct wiphy *wiphy) } /* set up regulatory info */ - wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); + regulatory_update(wiphy, NL80211_REGDOM_SET_BY_CORE); list_add_rcu(&rdev->list, &cfg80211_rdev_list); cfg80211_rdev_list_generation++; diff --git a/net/wireless/core.h b/net/wireless/core.h index 3dce1f1..0517d03 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -277,8 +277,6 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname); void ieee80211_set_bitrate_flags(struct wiphy *wiphy); -void wiphy_update_regulatory(struct wiphy *wiphy, - enum nl80211_reg_initiator setby); void cfg80211_bss_expire(struct cfg80211_registered_device *dev); void cfg80211_bss_age(struct cfg80211_registered_device *dev, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1ad0f39..a10dc34 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -912,14 +912,6 @@ static bool ignore_reg_update(struct wiphy *wiphy, return false; } -static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) -{ - struct cfg80211_registered_device *rdev; - - list_for_each_entry(rdev, &cfg80211_rdev_list, list) - wiphy_update_regulatory(&rdev->wiphy, initiator); -} - static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, struct reg_beacon *reg_beacon) @@ -1119,24 +1111,6 @@ static void reg_process_ht_flags(struct wiphy *wiphy) } -void wiphy_update_regulatory(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) -{ - enum ieee80211_band band; - - if (ignore_reg_update(wiphy, initiator)) - goto out; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (wiphy->bands[band]) - handle_band(wiphy, band, initiator); - } -out: - reg_process_beacons(wiphy); - reg_process_ht_flags(wiphy); - if (wiphy->reg_notifier) - wiphy->reg_notifier(wiphy, last_request); -} - static void handle_channel_custom(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx, @@ -1423,6 +1397,42 @@ new_request: return call_crda(last_request->alpha2); } +static void wiphy_update_regulatory(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + enum ieee80211_band band; + + assert_reg_lock(); + + if (ignore_reg_update(wiphy, initiator)) + goto out; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (wiphy->bands[band]) + handle_band(wiphy, band, initiator); + } +out: + reg_process_beacons(wiphy); + reg_process_ht_flags(wiphy); + if (wiphy->reg_notifier) + wiphy->reg_notifier(wiphy, last_request); +} + +static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) +{ + struct cfg80211_registered_device *rdev; + + list_for_each_entry(rdev, &cfg80211_rdev_list, list) + wiphy_update_regulatory(&rdev->wiphy, initiator); +} + +void regulatory_update(struct wiphy *wiphy, + enum nl80211_reg_initiator setby) +{ + mutex_lock(®_mutex); + wiphy_update_regulatory(wiphy, setby); + mutex_unlock(®_mutex); +} + /* This processes *all* regulatory hints */ static void reg_process_hint(struct regulatory_request *reg_request) { diff --git a/net/wireless/reg.h b/net/wireless/reg.h index b67d1c3..4a56799 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -16,6 +16,8 @@ void regulatory_exit(void); int set_regdom(const struct ieee80211_regdomain *rd); +void regulatory_update(struct wiphy *wiphy, enum nl80211_reg_initiator setby); + /** * regulatory_hint_found_beacon - hints a beacon was found on a channel * @wiphy: the wireless device where the beacon was found on -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html