Two fixes:
* bridge vs. 4-addr mode check was wrong * management frame registrations locking was wrong, causing list corruption/crashes -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmF5Y8AACgkQB8qZga/f l8SEGQ/+NJOZHSSQWcgfBpXzZ2ZN1Mk1Sgi/ZLSE/FbfbN3y/WQWgWR06RZ9djtE 6NzrIqMX7kuynRcTTFEYUT4ezl2XTb8CneLXqxHYKR8PXyRhyzo76bcxSCekp7Mr 4N4Rfaj8VAJ7Q+/skiWAevnFyhGBD9uG4KV78ytsBiCURQBW9MCHm+UObBImVxcH 0azqLZ+99++rXtraQhDSZZneY+/EKUIdpqM5iNVvx6X/Q+n8+Fb/0XcYmGE46TWH ZuHj+Vp8jJyNS8fsykL2O77sdiw5mnEVvYGumh8FfsP4fxndH8XSjRyMRfv1f4SU sKvsz2wcyFmIKisdZ9EA7uqnDXEDjodTO9OUCgg2VhI3TFJQ7A0ycU0yan1EnhPZ kVt/NkNyZgFFmedhN+XYaVXXda17qXHeeh6yWC1shO55H2e80Fj8//ETps1Jau1c u+xmf5DIKBnOsG+GnyYUJ3V9wLRedB0HI4KOIYjt2Nu/Vwp39Y/yK0HQ06uxLiGV QSOHSCjIhgVFmeez967UjIwDZesUxhVWA6M263qqkxWC75WmcDswuqkcWqgAcTat GEIfQi4W9FtBatLeny+uKcai++25cVJc+RZxQdKSDSfyocLPtvjZRpypBIYtMYgN PPp8xqMWFOd40TzK+R7+mu6RDop4UnlwAHAPwIbBGUX7n5IW410= =iErV -----END PGP SIGNATURE----- Merge tag 'mac80211-for-net-2021-10-27' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== Two fixes: * bridge vs. 4-addr mode check was wrong * management frame registrations locking was wrong, causing list corruption/crashes ==================== Link: https://lore.kernel.org/r/20211027143756.91711-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
afe8ca110c
@ -5376,7 +5376,6 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
|
||||
* netdev and may otherwise be used by driver read-only, will be update
|
||||
* by cfg80211 on change_interface
|
||||
* @mgmt_registrations: list of registrations for management frames
|
||||
* @mgmt_registrations_lock: lock for the list
|
||||
* @mgmt_registrations_need_update: mgmt registrations were updated,
|
||||
* need to propagate the update to the driver
|
||||
* @mtx: mutex used to lock data in this struct, may be used by drivers
|
||||
@ -5423,7 +5422,6 @@ struct wireless_dev {
|
||||
u32 identifier;
|
||||
|
||||
struct list_head mgmt_registrations;
|
||||
spinlock_t mgmt_registrations_lock;
|
||||
u8 mgmt_registrations_need_update:1;
|
||||
|
||||
struct mutex mtx;
|
||||
|
@ -524,6 +524,7 @@ use_default_name:
|
||||
INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
|
||||
INIT_WORK(&rdev->mgmt_registrations_update_wk,
|
||||
cfg80211_mgmt_registrations_update_wk);
|
||||
spin_lock_init(&rdev->mgmt_registrations_lock);
|
||||
|
||||
#ifdef CONFIG_CFG80211_DEFAULT_PS
|
||||
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
@ -1279,7 +1280,6 @@ void cfg80211_init_wdev(struct wireless_dev *wdev)
|
||||
INIT_LIST_HEAD(&wdev->event_list);
|
||||
spin_lock_init(&wdev->event_lock);
|
||||
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
||||
spin_lock_init(&wdev->mgmt_registrations_lock);
|
||||
INIT_LIST_HEAD(&wdev->pmsr_list);
|
||||
spin_lock_init(&wdev->pmsr_lock);
|
||||
INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
|
||||
|
@ -100,6 +100,8 @@ struct cfg80211_registered_device {
|
||||
struct work_struct propagate_cac_done_wk;
|
||||
|
||||
struct work_struct mgmt_registrations_update_wk;
|
||||
/* lock for all wdev lists */
|
||||
spinlock_t mgmt_registrations_lock;
|
||||
|
||||
/* must be last because of the way we do wiphy_priv(),
|
||||
* and it should at least be aligned to NETDEV_ALIGN */
|
||||
|
@ -452,9 +452,9 @@ static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
|
||||
|
||||
lockdep_assert_held(&rdev->wiphy.mtx);
|
||||
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_lock_bh(&rdev->mgmt_registrations_lock);
|
||||
if (!wdev->mgmt_registrations_need_update) {
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
|
||||
rcu_read_unlock();
|
||||
|
||||
wdev->mgmt_registrations_need_update = 0;
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
|
||||
}
|
||||
@ -503,6 +503,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||
int match_len, bool multicast_rx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct cfg80211_mgmt_registration *reg, *nreg;
|
||||
int err = 0;
|
||||
u16 mgmt_type;
|
||||
@ -548,7 +549,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||
if (!nreg)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_lock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
|
||||
int mlen = min(match_len, reg->match_len);
|
||||
@ -583,7 +584,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||
list_add(&nreg->list, &wdev->mgmt_registrations);
|
||||
}
|
||||
wdev->mgmt_registrations_need_update = 1;
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
cfg80211_mgmt_registrations_update(wdev);
|
||||
|
||||
@ -591,7 +592,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||
|
||||
out:
|
||||
kfree(nreg);
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -602,7 +603,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct cfg80211_mgmt_registration *reg, *tmp;
|
||||
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_lock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
|
||||
if (reg->nlportid != nlportid)
|
||||
@ -615,7 +616,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
|
||||
schedule_work(&rdev->mgmt_registrations_update_wk);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
if (nlportid && rdev->crit_proto_nlportid == nlportid) {
|
||||
rdev->crit_proto_nlportid = 0;
|
||||
@ -628,15 +629,16 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
|
||||
|
||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct cfg80211_mgmt_registration *reg, *tmp;
|
||||
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_lock_bh(&rdev->mgmt_registrations_lock);
|
||||
list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
|
||||
list_del(®->list);
|
||||
kfree(reg);
|
||||
}
|
||||
wdev->mgmt_registrations_need_update = 1;
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
cfg80211_mgmt_registrations_update(wdev);
|
||||
}
|
||||
@ -784,7 +786,7 @@ bool cfg80211_rx_mgmt_khz(struct wireless_dev *wdev, int freq, int sig_dbm,
|
||||
data = buf + ieee80211_hdrlen(mgmt->frame_control);
|
||||
data_len = len - ieee80211_hdrlen(mgmt->frame_control);
|
||||
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_lock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
|
||||
if (reg->frame_type != ftype)
|
||||
@ -808,7 +810,7 @@ bool cfg80211_rx_mgmt_khz(struct wireless_dev *wdev, int freq, int sig_dbm,
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
spin_unlock_bh(&rdev->mgmt_registrations_lock);
|
||||
|
||||
trace_cfg80211_return_bool(result);
|
||||
return result;
|
||||
|
@ -1028,14 +1028,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
!(rdev->wiphy.interface_modes & (1 << ntype)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* if it's part of a bridge, reject changing type to station/ibss */
|
||||
if (netif_is_bridge_port(dev) &&
|
||||
(ntype == NL80211_IFTYPE_ADHOC ||
|
||||
ntype == NL80211_IFTYPE_STATION ||
|
||||
ntype == NL80211_IFTYPE_P2P_CLIENT))
|
||||
return -EBUSY;
|
||||
|
||||
if (ntype != otype) {
|
||||
/* if it's part of a bridge, reject changing type to station/ibss */
|
||||
if (netif_is_bridge_port(dev) &&
|
||||
(ntype == NL80211_IFTYPE_ADHOC ||
|
||||
ntype == NL80211_IFTYPE_STATION ||
|
||||
ntype == NL80211_IFTYPE_P2P_CLIENT))
|
||||
return -EBUSY;
|
||||
|
||||
dev->ieee80211_ptr->use_4addr = false;
|
||||
dev->ieee80211_ptr->mesh_id_up_len = 0;
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
|
Loading…
x
Reference in New Issue
Block a user