aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-05-01 18:44:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-04 16:22:12 -0400
commitac46d48e00349c63650b3cc6f9460fcc183da6a6 (patch)
treea6516d0c1e62e3b32baad0bcee0db6a3f3d7cd73
parent299f5462087f3bc2141e6bc83ba7e2b15d8a07d2 (diff)
cfg80211: fix race condition with wiphy_apply_custom_regulatory()
We forgot to lock using the cfg80211_mutex in wiphy_apply_custom_regulatory(). Without the lock there is possible race between processing a reply from CRDA and a driver calling wiphy_apply_custom_regulatory(). During the processing of the reply from CRDA we free last_request and wiphy_apply_custom_regulatory() eventually accesses an element from last_request in the through freq_reg_info_regd(). This is very difficult to reproduce (I haven't), it takes us 3 hours and you need to be banging hard, but the race is obvious by looking at the code. This should only affect those who use this caller, which currently is ath5k, ath9k, and ar9170. EIP: 0060:[<f8ebec50>] EFLAGS: 00210282 CPU: 1 EIP is at freq_reg_info_regd+0x24/0x121 [cfg80211] EAX: 00000000 EBX: f7ca0060 ECX: f5183d94 EDX: 0024cde0 ESI: f8f56edc EDI: 00000000 EBP: 00000000 ESP: f5183d44 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Process modprobe (pid: 14617, ti=f5182000 task=f3934d10 task.ti=f5182000) Stack: c0505300 f7ca0ab4 f5183d94 0024cde0 f8f403a6 f8f63160 f7ca0060 00000000 00000000 f8ebedf8 f5183d90 f8f56edc 00000000 00000004 00000f40 f8f56edc f7ca0060 f7ca1234 00000000 00000000 00000000 f7ca14f0 f7ca0ab4 f7ca1289 Call Trace: [<f8ebedf8>] wiphy_apply_custom_regulatory+0x8f/0x122 [cfg80211] [<f8f3f798>] ath_attach+0x707/0x9e6 [ath9k] [<f8f45e46>] ath_pci_probe+0x18d/0x29a [ath9k] [<c023c7ba>] pci_device_probe+0xa3/0xe4 [<c02a860b>] really_probe+0xd7/0x1de [<c02a87e7>] __driver_attach+0x37/0x55 [<c02a7eed>] bus_for_each_dev+0x31/0x57 [<c02a83bd>] driver_attach+0x16/0x18 [<c02a78e6>] bus_add_driver+0xec/0x21b [<c02a8959>] driver_register+0x85/0xe2 [<c023c9bb>] __pci_register_driver+0x3c/0x69 [<f8e93043>] ath9k_init+0x43/0x68 [ath9k] [<c010112b>] _stext+0x3b/0x116 [<c014a872>] sys_init_module+0x8a/0x19e [<c01049ad>] sysenter_do_call+0x12/0x21 [<ffffe430>] 0xffffe430 ======================= Code: 0f 94 c0 c3 31 c0 c3 55 57 56 53 89 c3 83 ec 14 8b 74 24 2c 89 54 24 0c 89 4c 24 08 85 f6 75 06 8b 35 c8 bb ec f8 a1 cc bb ec f8 <8b> 40 04 83 f8 03 74 3a 48 74 37 8b 43 28 85 c0 74 30 89 c6 8b EIP: [<f8ebec50>] freq_reg_info_regd+0x24/0x121 [cfg80211] SS:ESP 0068:f5183d44 Cc: stable@kernel.org Reported-by: Nataraj Sadasivam <Nataraj.Sadasivam@Atheros.com> Reported-by: Vivek Natarajan <Vivek.Natarajan@Atheros.com> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/wireless/reg.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 6c1993d99902..3a734949769d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -907,6 +907,7 @@ EXPORT_SYMBOL(freq_reg_info);
907int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, 907int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth,
908 const struct ieee80211_reg_rule **reg_rule) 908 const struct ieee80211_reg_rule **reg_rule)
909{ 909{
910 assert_cfg80211_lock();
910 return freq_reg_info_regd(wiphy, center_freq, 911 return freq_reg_info_regd(wiphy, center_freq,
911 bandwidth, reg_rule, NULL); 912 bandwidth, reg_rule, NULL);
912} 913}
@@ -1176,6 +1177,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
1176 struct ieee80211_supported_band *sband; 1177 struct ieee80211_supported_band *sband;
1177 struct ieee80211_channel *chan; 1178 struct ieee80211_channel *chan;
1178 1179
1180 assert_cfg80211_lock();
1181
1179 sband = wiphy->bands[band]; 1182 sband = wiphy->bands[band];
1180 BUG_ON(chan_idx >= sband->n_channels); 1183 BUG_ON(chan_idx >= sband->n_channels);
1181 chan = &sband->channels[chan_idx]; 1184 chan = &sband->channels[chan_idx];
@@ -1214,10 +1217,13 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1214 const struct ieee80211_regdomain *regd) 1217 const struct ieee80211_regdomain *regd)
1215{ 1218{
1216 enum ieee80211_band band; 1219 enum ieee80211_band band;
1220
1221 mutex_lock(&cfg80211_mutex);
1217 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1222 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1218 if (wiphy->bands[band]) 1223 if (wiphy->bands[band])
1219 handle_band_custom(wiphy, band, regd); 1224 handle_band_custom(wiphy, band, regd);
1220 } 1225 }
1226 mutex_unlock(&cfg80211_mutex);
1221} 1227}
1222EXPORT_SYMBOL(wiphy_apply_custom_regulatory); 1228EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
1223 1229