Skip to content

Commit 0256317

Browse files
committed
Merge tag 'mac80211-next-for-net-next-2021-02-02' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== This time, only RTNL locking reduction fallout. - cfg80211_dev_rename() requires RTNL - cfg80211_change_iface() and cfg80211_set_encryption() require wiphy mutex (was missing in wireless extensions) - cfg80211_destroy_ifaces() requires wiphy mutex - netdev registration can fail due to notifiers, and then notifiers are "unrolled", need to handle this properly * tag 'mac80211-next-for-net-next-2021-02-02' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next: cfg80211: fix netdev registration deadlock cfg80211: call cfg80211_destroy_ifaces() with wiphy lock held wext: call cfg80211_set_encryption() with wiphy lock held wext: call cfg80211_change_iface() with wiphy lock held nl80211: call cfg80211_dev_rename() under RTNL ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 390d9b5 + 40c575d commit 0256317

File tree

4 files changed

+22
-5
lines changed

4 files changed

+22
-5
lines changed

include/net/cfg80211.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5299,6 +5299,8 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
52995299
* @wiphy: pointer to hardware description
53005300
* @iftype: interface type
53015301
* @registered: is this wdev already registered with cfg80211
5302+
* @registering: indicates we're doing registration under wiphy lock
5303+
* for the notifier
53025304
* @list: (private) Used to collect the interfaces
53035305
* @netdev: (private) Used to reference back to the netdev, may be %NULL
53045306
* @identifier: (private) Identifier used in nl80211 to identify this
@@ -5382,7 +5384,7 @@ struct wireless_dev {
53825384

53835385
struct mutex mtx;
53845386

5385-
bool use_4addr, is_running, registered;
5387+
bool use_4addr, is_running, registered, registering;
53865388

53875389
u8 address[ETH_ALEN] __aligned(sizeof(u16));
53885390

net/wireless/core.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
334334
struct wireless_dev *wdev, *tmp;
335335

336336
ASSERT_RTNL();
337+
lockdep_assert_wiphy(&rdev->wiphy);
337338

338339
list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
339340
if (wdev->nl_owner_dead)
@@ -349,7 +350,9 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work)
349350
destroy_work);
350351

351352
rtnl_lock();
353+
wiphy_lock(&rdev->wiphy);
352354
cfg80211_destroy_ifaces(rdev);
355+
wiphy_unlock(&rdev->wiphy);
353356
rtnl_unlock();
354357
}
355358

@@ -1343,6 +1346,7 @@ int cfg80211_register_netdevice(struct net_device *dev)
13431346

13441347
/* we'll take care of this */
13451348
wdev->registered = true;
1349+
wdev->registering = true;
13461350
ret = register_netdevice(dev);
13471351
if (ret)
13481352
goto out;
@@ -1358,6 +1362,7 @@ int cfg80211_register_netdevice(struct net_device *dev)
13581362
cfg80211_register_wdev(rdev, wdev);
13591363
ret = 0;
13601364
out:
1365+
wdev->registering = false;
13611366
if (ret)
13621367
wdev->registered = false;
13631368
return ret;
@@ -1400,7 +1405,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
14001405
* It is possible to get NETDEV_UNREGISTER multiple times,
14011406
* so check wdev->registered.
14021407
*/
1403-
if (wdev->registered) {
1408+
if (wdev->registered && !wdev->registering) {
14041409
wiphy_lock(&rdev->wiphy);
14051410
_cfg80211_unregister_wdev(wdev, false);
14061411
wiphy_unlock(&rdev->wiphy);

net/wireless/nl80211.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3220,7 +3220,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
32203220
wdev = netdev->ieee80211_ptr;
32213221

32223222
wiphy_lock(&rdev->wiphy);
3223-
rtnl_unlock();
32243223

32253224
/*
32263225
* end workaround code, by now the rdev is available
@@ -3230,6 +3229,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
32303229
if (info->attrs[NL80211_ATTR_WIPHY_NAME])
32313230
result = cfg80211_dev_rename(
32323231
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
3232+
rtnl_unlock();
32333233

32343234
if (result)
32353235
goto out;

net/wireless/wext-compat.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
3939
struct cfg80211_registered_device *rdev;
4040
struct vif_params vifparams;
4141
enum nl80211_iftype type;
42+
int ret;
4243

4344
rdev = wiphy_to_rdev(wdev->wiphy);
4445

@@ -61,7 +62,11 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
6162

6263
memset(&vifparams, 0, sizeof(vifparams));
6364

64-
return cfg80211_change_iface(rdev, dev, type, &vifparams);
65+
wiphy_lock(wdev->wiphy);
66+
ret = cfg80211_change_iface(rdev, dev, type, &vifparams);
67+
wiphy_unlock(wdev->wiphy);
68+
69+
return ret;
6570
}
6671
EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode);
6772

@@ -650,6 +655,7 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
650655
bool remove = false;
651656
struct key_params params;
652657
u32 cipher;
658+
int ret;
653659

654660
if (wdev->iftype != NL80211_IFTYPE_STATION &&
655661
wdev->iftype != NL80211_IFTYPE_ADHOC)
@@ -721,12 +727,16 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
721727
params.seq_len = 6;
722728
}
723729

724-
return cfg80211_set_encryption(
730+
wiphy_lock(wdev->wiphy);
731+
ret = cfg80211_set_encryption(
725732
rdev, dev,
726733
!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
727734
addr, remove,
728735
ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
729736
idx, &params);
737+
wiphy_unlock(wdev->wiphy);
738+
739+
return ret;
730740
}
731741

732742
static int cfg80211_wext_giwencode(struct net_device *dev,

0 commit comments

Comments
 (0)