Commit 4b181144e6c1c25aaba9b9fc7cc70c95495ecb92
Committed by
John W. Linville
1 parent
e312c24cf8
Exists in
master
and in
7 other branches
cfg80211: fix locking for SIWFREQ
"cfg80211: validate channel settings across interfaces" contained a locking bug -- in the managed-mode SIWFREQ call it would end up running into a lock recursion. This fixes it by not checking that particular interface for a channel that it needs to stay on, which is as it should be as that's the interface we're setting the channel for. Reported-by: Reinette Chatre <reinette.chatre@intel.com> Reported-by: Kalle Valo <kalle.valo@iki.fi> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Tested-by: Kalle Valo <kalle.valo@iki.fi> Tested-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 5 changed files with 6 additions and 4 deletions Side-by-side Diff
net/wireless/chan.c
... | ... | @@ -42,13 +42,14 @@ |
42 | 42 | } |
43 | 43 | |
44 | 44 | int rdev_set_freq(struct cfg80211_registered_device *rdev, |
45 | + struct wireless_dev *for_wdev, | |
45 | 46 | int freq, enum nl80211_channel_type channel_type) |
46 | 47 | { |
47 | 48 | struct ieee80211_channel *chan; |
48 | 49 | struct ieee80211_sta_ht_cap *ht_cap; |
49 | 50 | int result; |
50 | 51 | |
51 | - if (rdev_fixed_channel(rdev, NULL)) | |
52 | + if (rdev_fixed_channel(rdev, for_wdev)) | |
52 | 53 | return -EBUSY; |
53 | 54 | |
54 | 55 | if (!rdev->ops->set_channel) |
net/wireless/core.h
... | ... | @@ -374,6 +374,7 @@ |
374 | 374 | rdev_fixed_channel(struct cfg80211_registered_device *rdev, |
375 | 375 | struct wireless_dev *for_wdev); |
376 | 376 | int rdev_set_freq(struct cfg80211_registered_device *rdev, |
377 | + struct wireless_dev *for_wdev, | |
377 | 378 | int freq, enum nl80211_channel_type channel_type); |
378 | 379 | |
379 | 380 | #endif /* __NET_WIRELESS_CORE_H */ |
net/wireless/nl80211.c
... | ... | @@ -721,7 +721,7 @@ |
721 | 721 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
722 | 722 | |
723 | 723 | mutex_lock(&rdev->devlist_mtx); |
724 | - result = rdev_set_freq(rdev, freq, channel_type); | |
724 | + result = rdev_set_freq(rdev, NULL, freq, channel_type); | |
725 | 725 | mutex_unlock(&rdev->devlist_mtx); |
726 | 726 | if (result) |
727 | 727 | goto bad_res; |
net/wireless/wext-compat.c
... | ... | @@ -766,7 +766,7 @@ |
766 | 766 | if (freq == 0) |
767 | 767 | return -EINVAL; |
768 | 768 | mutex_lock(&rdev->devlist_mtx); |
769 | - err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT); | |
769 | + err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT); | |
770 | 770 | mutex_unlock(&rdev->devlist_mtx); |
771 | 771 | return err; |
772 | 772 | } |
net/wireless/wext-sme.c
... | ... | @@ -106,7 +106,7 @@ |
106 | 106 | |
107 | 107 | /* SSID is not set, we just want to switch channel */ |
108 | 108 | if (chan && !wdev->wext.connect.ssid_len) { |
109 | - err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT); | |
109 | + err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); | |
110 | 110 | goto out; |
111 | 111 | } |
112 | 112 |