Commit 0256317a authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'mac80211-next-for-net-next-2021-02-02' of...

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/20210202144106.38207-1-johannes@sipsolutions.netSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 390d9b56 40c575d1
...@@ -5299,6 +5299,8 @@ static inline void wiphy_unlock(struct wiphy *wiphy) ...@@ -5299,6 +5299,8 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
* @wiphy: pointer to hardware description * @wiphy: pointer to hardware description
* @iftype: interface type * @iftype: interface type
* @registered: is this wdev already registered with cfg80211 * @registered: is this wdev already registered with cfg80211
* @registering: indicates we're doing registration under wiphy lock
* for the notifier
* @list: (private) Used to collect the interfaces * @list: (private) Used to collect the interfaces
* @netdev: (private) Used to reference back to the netdev, may be %NULL * @netdev: (private) Used to reference back to the netdev, may be %NULL
* @identifier: (private) Identifier used in nl80211 to identify this * @identifier: (private) Identifier used in nl80211 to identify this
...@@ -5382,7 +5384,7 @@ struct wireless_dev { ...@@ -5382,7 +5384,7 @@ struct wireless_dev {
struct mutex mtx; struct mutex mtx;
bool use_4addr, is_running, registered; bool use_4addr, is_running, registered, registering;
u8 address[ETH_ALEN] __aligned(sizeof(u16)); u8 address[ETH_ALEN] __aligned(sizeof(u16));
......
...@@ -334,6 +334,7 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) ...@@ -334,6 +334,7 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
struct wireless_dev *wdev, *tmp; struct wireless_dev *wdev, *tmp;
ASSERT_RTNL(); ASSERT_RTNL();
lockdep_assert_wiphy(&rdev->wiphy);
list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) { list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
if (wdev->nl_owner_dead) if (wdev->nl_owner_dead)
...@@ -349,7 +350,9 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work) ...@@ -349,7 +350,9 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work)
destroy_work); destroy_work);
rtnl_lock(); rtnl_lock();
wiphy_lock(&rdev->wiphy);
cfg80211_destroy_ifaces(rdev); cfg80211_destroy_ifaces(rdev);
wiphy_unlock(&rdev->wiphy);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -1343,6 +1346,7 @@ int cfg80211_register_netdevice(struct net_device *dev) ...@@ -1343,6 +1346,7 @@ int cfg80211_register_netdevice(struct net_device *dev)
/* we'll take care of this */ /* we'll take care of this */
wdev->registered = true; wdev->registered = true;
wdev->registering = true;
ret = register_netdevice(dev); ret = register_netdevice(dev);
if (ret) if (ret)
goto out; goto out;
...@@ -1358,6 +1362,7 @@ int cfg80211_register_netdevice(struct net_device *dev) ...@@ -1358,6 +1362,7 @@ int cfg80211_register_netdevice(struct net_device *dev)
cfg80211_register_wdev(rdev, wdev); cfg80211_register_wdev(rdev, wdev);
ret = 0; ret = 0;
out: out:
wdev->registering = false;
if (ret) if (ret)
wdev->registered = false; wdev->registered = false;
return ret; return ret;
...@@ -1400,7 +1405,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1400,7 +1405,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* It is possible to get NETDEV_UNREGISTER multiple times, * It is possible to get NETDEV_UNREGISTER multiple times,
* so check wdev->registered. * so check wdev->registered.
*/ */
if (wdev->registered) { if (wdev->registered && !wdev->registering) {
wiphy_lock(&rdev->wiphy); wiphy_lock(&rdev->wiphy);
_cfg80211_unregister_wdev(wdev, false); _cfg80211_unregister_wdev(wdev, false);
wiphy_unlock(&rdev->wiphy); wiphy_unlock(&rdev->wiphy);
......
...@@ -3220,7 +3220,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -3220,7 +3220,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
wdev = netdev->ieee80211_ptr; wdev = netdev->ieee80211_ptr;
wiphy_lock(&rdev->wiphy); wiphy_lock(&rdev->wiphy);
rtnl_unlock();
/* /*
* end workaround code, by now the rdev is available * 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) ...@@ -3230,6 +3229,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_NAME]) if (info->attrs[NL80211_ATTR_WIPHY_NAME])
result = cfg80211_dev_rename( result = cfg80211_dev_rename(
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
rtnl_unlock();
if (result) if (result)
goto out; goto out;
......
...@@ -39,6 +39,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, ...@@ -39,6 +39,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
struct vif_params vifparams; struct vif_params vifparams;
enum nl80211_iftype type; enum nl80211_iftype type;
int ret;
rdev = wiphy_to_rdev(wdev->wiphy); rdev = wiphy_to_rdev(wdev->wiphy);
...@@ -61,7 +62,11 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, ...@@ -61,7 +62,11 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams)); memset(&vifparams, 0, sizeof(vifparams));
return cfg80211_change_iface(rdev, dev, type, &vifparams); wiphy_lock(wdev->wiphy);
ret = cfg80211_change_iface(rdev, dev, type, &vifparams);
wiphy_unlock(wdev->wiphy);
return ret;
} }
EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode);
...@@ -650,6 +655,7 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev, ...@@ -650,6 +655,7 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
bool remove = false; bool remove = false;
struct key_params params; struct key_params params;
u32 cipher; u32 cipher;
int ret;
if (wdev->iftype != NL80211_IFTYPE_STATION && if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_ADHOC) wdev->iftype != NL80211_IFTYPE_ADHOC)
...@@ -721,12 +727,16 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev, ...@@ -721,12 +727,16 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
params.seq_len = 6; params.seq_len = 6;
} }
return cfg80211_set_encryption( wiphy_lock(wdev->wiphy);
ret = cfg80211_set_encryption(
rdev, dev, rdev, dev,
!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY), !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
addr, remove, addr, remove,
ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
idx, &params); idx, &params);
wiphy_unlock(wdev->wiphy);
return ret;
} }
static int cfg80211_wext_giwencode(struct net_device *dev, static int cfg80211_wext_giwencode(struct net_device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment