History

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 ====================

Jakub Kicinski committed 5 years ago

Commit afe8ca12 parents 424a4f5 689a0a95 files · +24 −22Browse files

Unified · Split

5 files
  1. include/net/cfg80211.h +0 −2
  2. net/wireless/core.c +1 −1
  3. net/wireless/core.h +2 −0
  4. net/wireless/mlme.c +14 −12
  5. net/wireless/util.c +7 −7
include/net/cfg80211.h+0−2
@@ -5376,7 +5376,6 @@ static inline void wiphy_unlock(struct wiphy *wiphy) · 5375 unmodified lines
53765376 * netdev and may otherwise be used by driver read-only, will be update
53775377 * by cfg80211 on change_interface
53785378 * @mgmt_registrations: list of registrations for management frames
5379− * @mgmt_registrations_lock: lock for the list
53805379 * @mgmt_registrations_need_update: mgmt registrations were updated,
53815380 * need to propagate the update to the driver
53825381 * @mtx: mutex used to lock data in this struct, may be used by drivers
@@ -5423,7 +5422,6 @@ struct wireless_dev { · 40 unmodified lines
54235422 u32 identifier;
54245423
54255424 struct list_head mgmt_registrations;
5426− spinlock_t mgmt_registrations_lock;
54275425 u8 mgmt_registrations_need_update:1;
54285426
54295427 struct mutex mtx;
net/wireless/core.c+1−1
@@ -524,6 +524,7 @@ use_default_name: · 523 unmodified lines
524524 INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
525525 INIT_WORK(&rdev->mgmt_registrations_update_wk,
526526 cfg80211_mgmt_registrations_update_wk);
527+ spin_lock_init(&rdev->mgmt_registrations_lock);
527528
528529 #ifdef CONFIG_CFG80211_DEFAULT_PS
529530 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -1279,7 +1280,6 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) · 749 unmodified lines
12791280 INIT_LIST_HEAD(&wdev->event_list);
12801281 spin_lock_init(&wdev->event_lock);
12811282 INIT_LIST_HEAD(&wdev->mgmt_registrations);
1282− spin_lock_init(&wdev->mgmt_registrations_lock);
12831283 INIT_LIST_HEAD(&wdev->pmsr_list);
12841284 spin_lock_init(&wdev->pmsr_lock);
12851285 INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
net/wireless/core.h+2−0
@@ -100,6 +100,8 @@ struct cfg80211_registered_device { · 99 unmodified lines
100100 struct work_struct propagate_cac_done_wk;
101101
102102 struct work_struct mgmt_registrations_update_wk;
103+ /* lock for all wdev lists */
104+ spinlock_t mgmt_registrations_lock;
103105
104106 /* must be last because of the way we do wiphy_priv(),
105107 * and it should at least be aligned to NETDEV_ALIGN */
net/wireless/mlme.c+14−12
@@ -452,9 +452,9 @@ static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev) · 451 unmodified lines
452452
453453 lockdep_assert_held(&rdev->wiphy.mtx);
454454
455− spin_lock_bh(&wdev->mgmt_registrations_lock);
455+ spin_lock_bh(&rdev->mgmt_registrations_lock);
456456 if (!wdev->mgmt_registrations_need_update) {
457− spin_unlock_bh(&wdev->mgmt_registrations_lock);
457+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
458458 return;
459459 }
460460
@@ -479,7 +479,7 @@ static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev) · 18 unmodified lines
479479 rcu_read_unlock();
480480
481481 wdev->mgmt_registrations_need_update = 0;
482− spin_unlock_bh(&wdev->mgmt_registrations_lock);
482+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
483483
484484 rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
485485 }
@@ -503,6 +503,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 17 unmodified lines
503503 int match_len, bool multicast_rx,
504504 struct netlink_ext_ack *extack)
505505 {
506+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
506507 struct cfg80211_mgmt_registration *reg, *nreg;
507508 int err = 0;
508509 u16 mgmt_type;
@@ -548,7 +549,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 39 unmodified lines
548549 if (!nreg)
549550 return -ENOMEM;
550551
551− spin_lock_bh(&wdev->mgmt_registrations_lock);
552+ spin_lock_bh(&rdev->mgmt_registrations_lock);
552553
553554 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
554555 int mlen = min(match_len, reg->match_len);
@@ -583,7 +584,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 28 unmodified lines
583584 list_add(&nreg->list, &wdev->mgmt_registrations);
584585 }
585586 wdev->mgmt_registrations_need_update = 1;
586− spin_unlock_bh(&wdev->mgmt_registrations_lock);
587+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
587588
588589 cfg80211_mgmt_registrations_update(wdev);
589590
@@ -591,7 +592,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 1 unmodified line
591592
592593 out:
593594 kfree(nreg);
594− spin_unlock_bh(&wdev->mgmt_registrations_lock);
595+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
595596
596597 return err;
597598 }
@@ -602,7 +603,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 4 unmodified lines
602603 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
603604 struct cfg80211_mgmt_registration *reg, *tmp;
604605
605− spin_lock_bh(&wdev->mgmt_registrations_lock);
606+ spin_lock_bh(&rdev->mgmt_registrations_lock);
606607
607608 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
608609 if (reg->nlportid != nlportid)
@@ -615,7 +616,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 6 unmodified lines
615616 schedule_work(&rdev->mgmt_registrations_update_wk);
616617 }
617618
618− spin_unlock_bh(&wdev->mgmt_registrations_lock);
619+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
619620
620621 if (nlportid && rdev->crit_proto_nlportid == nlportid) {
621622 rdev->crit_proto_nlportid = 0;
@@ -628,15 +629,16 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 6 unmodified lines
628629
629630 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
630631 {
632+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
631633 struct cfg80211_mgmt_registration *reg, *tmp;
632634
633− spin_lock_bh(&wdev->mgmt_registrations_lock);
635+ spin_lock_bh(&rdev->mgmt_registrations_lock);
634636 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
635637 list_del(&reg->list);
636638 kfree(reg);
637639 }
638640 wdev->mgmt_registrations_need_update = 1;
639− spin_unlock_bh(&wdev->mgmt_registrations_lock);
641+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
640642
641643 cfg80211_mgmt_registrations_update(wdev);
642644 }
@@ -784,7 +786,7 @@ bool cfg80211_rx_mgmt_khz(struct wireless_dev *wdev, int freq, int sig_dbm, · 141 unmodified lines
784786 data = buf + ieee80211_hdrlen(mgmt->frame_control);
785787 data_len = len - ieee80211_hdrlen(mgmt->frame_control);
786788
787− spin_lock_bh(&wdev->mgmt_registrations_lock);
789+ spin_lock_bh(&rdev->mgmt_registrations_lock);
788790
789791 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
790792 if (reg->frame_type != ftype)
@@ -808,7 +810,7 @@ bool cfg80211_rx_mgmt_khz(struct wireless_dev *wdev, int freq, int sig_dbm, · 17 unmodified lines
808810 break;
809811 }
810812
811− spin_unlock_bh(&wdev->mgmt_registrations_lock);
813+ spin_unlock_bh(&rdev->mgmt_registrations_lock);
812814
813815 trace_cfg80211_return_bool(result);
814816 return result;
net/wireless/util.c+7−7
@@ -1028,14 +1028,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 1027 unmodified lines
10281028 !(rdev->wiphy.interface_modes & (1 << ntype)))
10291029 return -EOPNOTSUPP;
10301030
1031− /* if it's part of a bridge, reject changing type to station/ibss */
1032− if (netif_is_bridge_port(dev) &&
1033− (ntype == NL80211_IFTYPE_ADHOC ||
1034− ntype == NL80211_IFTYPE_STATION ||
1035− ntype == NL80211_IFTYPE_P2P_CLIENT))
1036− return -EBUSY;
1037−
10381031 if (ntype != otype) {
1032+ /* if it's part of a bridge, reject changing type to station/ibss */
1033+ if (netif_is_bridge_port(dev) &&
1034+ (ntype == NL80211_IFTYPE_ADHOC ||
1035+ ntype == NL80211_IFTYPE_STATION ||
1036+ ntype == NL80211_IFTYPE_P2P_CLIENT))
1037+ return -EBUSY;
1038+
10391039 dev->ieee80211_ptr->use_4addr = false;
10401040 dev->ieee80211_ptr->mesh_id_up_len = 0;
10411041 wdev_lock(dev->ieee80211_ptr);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t