Skip to content

Commit 7483a21

Browse files
committed
wifi: cfg80211: check RTNL when iterating devices
Add a new "for_each_rdev()" macro and check that we hold the RTNL when calling it. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent e911a81 commit 7483a21

File tree

6 files changed

+27
-17
lines changed

6 files changed

+27
-17
lines changed

net/wireless/chan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
823823
if (!(chan->flags & IEEE80211_CHAN_RADAR))
824824
return false;
825825

826-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
826+
for_each_rdev(rdev) {
827827
if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
828828
continue;
829829

net/wireless/core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
6060

6161
ASSERT_RTNL();
6262

63-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
63+
for_each_rdev(rdev) {
6464
if (rdev->wiphy_idx == wiphy_idx) {
6565
result = rdev;
6666
break;
@@ -116,7 +116,7 @@ static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
116116
}
117117

118118
/* Ensure another device does not already have this name. */
119-
list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
119+
for_each_rdev(rdev2)
120120
if (strcmp(newname, wiphy_name(&rdev2->wiphy)) == 0)
121121
return -EINVAL;
122122

@@ -1601,7 +1601,7 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
16011601
struct cfg80211_registered_device *rdev;
16021602

16031603
rtnl_lock();
1604-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1604+
for_each_rdev(rdev) {
16051605
if (net_eq(wiphy_net(&rdev->wiphy), net))
16061606
WARN_ON(cfg80211_switch_netns(rdev, &init_net));
16071607
}

net/wireless/core.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ extern struct workqueue_struct *cfg80211_wq;
160160
extern struct list_head cfg80211_rdev_list;
161161
extern int cfg80211_rdev_list_generation;
162162

163+
/* This is constructed like this so it can be used in if/else */
164+
static inline int for_each_rdev_check_rtnl(void)
165+
{
166+
ASSERT_RTNL();
167+
return 0;
168+
}
169+
#define for_each_rdev(rdev) \
170+
if (for_each_rdev_check_rtnl()) {} else \
171+
list_for_each_entry(rdev, &cfg80211_rdev_list, list)
172+
163173
struct cfg80211_internal_bss {
164174
struct list_head list;
165175
struct list_head hidden_list;

net/wireless/nl80211.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ __cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev,
106106

107107
ASSERT_RTNL();
108108

109-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
109+
for_each_rdev(rdev) {
110110
struct wireless_dev *wdev;
111111

112112
if (wiphy_net(&rdev->wiphy) != netns)
@@ -3075,7 +3075,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
30753075
cb->args[0] = (long)state;
30763076
}
30773077

3078-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3078+
for_each_rdev(rdev) {
30793079
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
30803080
continue;
30813081
if (++idx <= state->start)
@@ -3985,7 +3985,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
39853985
filter_wiphy = cb->args[2] - 1;
39863986
}
39873987

3988-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3988+
for_each_rdev(rdev) {
39893989
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
39903990
continue;
39913991
if (wp_idx < wp_start) {

net/wireless/reg.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,7 +2461,7 @@ static void reg_check_chans_work(struct work_struct *work)
24612461
pr_debug("Verifying active interfaces after reg change\n");
24622462
rtnl_lock();
24632463

2464-
list_for_each_entry(rdev, &cfg80211_rdev_list, list)
2464+
for_each_rdev(rdev)
24652465
reg_leave_invalid_chans(&rdev->wiphy);
24662466

24672467
rtnl_unlock();
@@ -2515,7 +2515,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
25152515

25162516
ASSERT_RTNL();
25172517

2518-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2518+
for_each_rdev(rdev) {
25192519
wiphy = &rdev->wiphy;
25202520
wiphy_update_regulatory(wiphy, initiator);
25212521
}
@@ -2991,7 +2991,7 @@ static void wiphy_all_share_dfs_chan_state(struct wiphy *wiphy)
29912991

29922992
ASSERT_RTNL();
29932993

2994-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2994+
for_each_rdev(rdev) {
29952995
if (wiphy == &rdev->wiphy)
29962996
continue;
29972997
wiphy_share_dfs_chan_state(wiphy, &rdev->wiphy);
@@ -3057,7 +3057,7 @@ static void notify_self_managed_wiphys(struct regulatory_request *request)
30573057
struct cfg80211_registered_device *rdev;
30583058
struct wiphy *wiphy;
30593059

3060-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3060+
for_each_rdev(rdev) {
30613061
wiphy = &rdev->wiphy;
30623062
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
30633063
request->initiator == NL80211_REGDOM_SET_BY_USER)
@@ -3122,7 +3122,7 @@ static void reg_process_pending_beacon_hints(void)
31223122
list_del_init(&pending_beacon->list);
31233123

31243124
/* Applies the beacon hint to current wiphys */
3125-
list_for_each_entry(rdev, &cfg80211_rdev_list, list)
3125+
for_each_rdev(rdev)
31263126
wiphy_update_new_beacon(&rdev->wiphy, pending_beacon);
31273127

31283128
/* Remembers the beacon hint for new wiphys or reg changes */
@@ -3177,7 +3177,7 @@ static void reg_process_self_managed_hints(void)
31773177

31783178
ASSERT_RTNL();
31793179

3180-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3180+
for_each_rdev(rdev) {
31813181
wiphy_lock(&rdev->wiphy);
31823182
reg_process_self_managed_hint(&rdev->wiphy);
31833183
wiphy_unlock(&rdev->wiphy);
@@ -3517,7 +3517,7 @@ static void restore_regulatory_settings(bool reset_user, bool cached)
35173517
world_alpha2[0] = cfg80211_world_regdom->alpha2[0];
35183518
world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
35193519

3520-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3520+
for_each_rdev(rdev) {
35213521
if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
35223522
continue;
35233523
if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
@@ -3574,7 +3574,7 @@ static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag)
35743574
struct cfg80211_registered_device *rdev;
35753575
struct wireless_dev *wdev;
35763576

3577-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3577+
for_each_rdev(rdev) {
35783578
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
35793579
wdev_lock(wdev);
35803580
if (!(wdev->wiphy->regulatory_flags & flag)) {
@@ -4244,7 +4244,7 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
42444244
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
42454245
return;
42464246

4247-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
4247+
for_each_rdev(rdev) {
42484248
if (wiphy == &rdev->wiphy)
42494249
continue;
42504250

net/wireless/sme.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ static bool cfg80211_is_all_idle(void)
702702
* need not issue a disconnect hint and reset any info such
703703
* as chan dfs state, etc.
704704
*/
705-
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
705+
for_each_rdev(rdev) {
706706
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
707707
wdev_lock(wdev);
708708
if (wdev->conn || wdev->connected ||

0 commit comments

Comments
 (0)