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
5376 * netdev and may otherwise be used by driver read-only, will be update5376 * netdev and may otherwise be used by driver read-only, will be update
5377 * by cfg80211 on change_interface5377 * by cfg80211 on change_interface
5378 * @mgmt_registrations: list of registrations for management frames5378 * @mgmt_registrations: list of registrations for management frames
5379 * @mgmt_registrations_lock: lock for the list
5380 * @mgmt_registrations_need_update: mgmt registrations were updated,5379 * @mgmt_registrations_need_update: mgmt registrations were updated,
5381 * need to propagate the update to the driver5380 * need to propagate the update to the driver
5382 * @mtx: mutex used to lock data in this struct, may be used by drivers5381 * @mtx: mutex used to lock data in this struct, may be used by drivers
@@ -5423,7 +5422,6 @@ struct wireless_dev { · 40 unmodified lines
5423 u32 identifier;5422 u32 identifier;
5424 5423
5425 struct list_head mgmt_registrations;5424 struct list_head mgmt_registrations;
5426 spinlock_t mgmt_registrations_lock;
5427 u8 mgmt_registrations_need_update:1;5425 u8 mgmt_registrations_need_update:1;
5428 5426
5429 struct mutex mtx;5427 struct mutex mtx;
net/wireless/core.c+1−1
@@ -524,6 +524,7 @@ use_default_name: · 523 unmodified lines
524 INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);524 INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
525 INIT_WORK(&rdev->mgmt_registrations_update_wk,525 INIT_WORK(&rdev->mgmt_registrations_update_wk,
526 cfg80211_mgmt_registrations_update_wk);526 cfg80211_mgmt_registrations_update_wk);
527 spin_lock_init(&rdev->mgmt_registrations_lock);
527 528
528#ifdef CONFIG_CFG80211_DEFAULT_PS529#ifdef CONFIG_CFG80211_DEFAULT_PS
529 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;530 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -1279,7 +1280,6 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) · 749 unmodified lines
1279 INIT_LIST_HEAD(&wdev->event_list);1280 INIT_LIST_HEAD(&wdev->event_list);
1280 spin_lock_init(&wdev->event_lock);1281 spin_lock_init(&wdev->event_lock);
1281 INIT_LIST_HEAD(&wdev->mgmt_registrations);1282 INIT_LIST_HEAD(&wdev->mgmt_registrations);
1282 spin_lock_init(&wdev->mgmt_registrations_lock);
1283 INIT_LIST_HEAD(&wdev->pmsr_list);1283 INIT_LIST_HEAD(&wdev->pmsr_list);
1284 spin_lock_init(&wdev->pmsr_lock);1284 spin_lock_init(&wdev->pmsr_lock);
1285 INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);1285 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
100 struct work_struct propagate_cac_done_wk;100 struct work_struct propagate_cac_done_wk;
101 101
102 struct work_struct mgmt_registrations_update_wk;102 struct work_struct mgmt_registrations_update_wk;
103 /* lock for all wdev lists */
104 spinlock_t mgmt_registrations_lock;
103 105
104 /* must be last because of the way we do wiphy_priv(),106 /* must be last because of the way we do wiphy_priv(),
105 * and it should at least be aligned to NETDEV_ALIGN */107 * 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
452 452
453 lockdep_assert_held(&rdev->wiphy.mtx);453 lockdep_assert_held(&rdev->wiphy.mtx);
454 454
455 spin_lock_bh(&wdev->mgmt_registrations_lock);455 spin_lock_bh(&rdev->mgmt_registrations_lock);
456 if (!wdev->mgmt_registrations_need_update) {456 if (!wdev->mgmt_registrations_need_update) {
457 spin_unlock_bh(&wdev->mgmt_registrations_lock);457 spin_unlock_bh(&rdev->mgmt_registrations_lock);
458 return;458 return;
459 }459 }
460 460
@@ -479,7 +479,7 @@ static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev) · 18 unmodified lines
479 rcu_read_unlock();479 rcu_read_unlock();
480 480
481 wdev->mgmt_registrations_need_update = 0;481 wdev->mgmt_registrations_need_update = 0;
482 spin_unlock_bh(&wdev->mgmt_registrations_lock);482 spin_unlock_bh(&rdev->mgmt_registrations_lock);
483 483
484 rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);484 rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
485}485}
@@ -503,6 +503,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 17 unmodified lines
503 int match_len, bool multicast_rx,503 int match_len, bool multicast_rx,
504 struct netlink_ext_ack *extack)504 struct netlink_ext_ack *extack)
505{505{
506 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
506 struct cfg80211_mgmt_registration *reg, *nreg;507 struct cfg80211_mgmt_registration *reg, *nreg;
507 int err = 0;508 int err = 0;
508 u16 mgmt_type;509 u16 mgmt_type;
@@ -548,7 +549,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 39 unmodified lines
548 if (!nreg)549 if (!nreg)
549 return -ENOMEM;550 return -ENOMEM;
550 551
551 spin_lock_bh(&wdev->mgmt_registrations_lock);552 spin_lock_bh(&rdev->mgmt_registrations_lock);
552 553
553 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {554 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
554 int mlen = min(match_len, reg->match_len);555 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
583 list_add(&nreg->list, &wdev->mgmt_registrations);584 list_add(&nreg->list, &wdev->mgmt_registrations);
584 }585 }
585 wdev->mgmt_registrations_need_update = 1;586 wdev->mgmt_registrations_need_update = 1;
586 spin_unlock_bh(&wdev->mgmt_registrations_lock);587 spin_unlock_bh(&rdev->mgmt_registrations_lock);
587 588
588 cfg80211_mgmt_registrations_update(wdev);589 cfg80211_mgmt_registrations_update(wdev);
589 590
@@ -591,7 +592,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 1 unmodified line
591 592
592 out:593 out:
593 kfree(nreg);594 kfree(nreg);
594 spin_unlock_bh(&wdev->mgmt_registrations_lock);595 spin_unlock_bh(&rdev->mgmt_registrations_lock);
595 596
596 return err;597 return err;
597}598}
@@ -602,7 +603,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 4 unmodified lines
602 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);603 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
603 struct cfg80211_mgmt_registration *reg, *tmp;604 struct cfg80211_mgmt_registration *reg, *tmp;
604 605
605 spin_lock_bh(&wdev->mgmt_registrations_lock);606 spin_lock_bh(&rdev->mgmt_registrations_lock);
606 607
607 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {608 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
608 if (reg->nlportid != nlportid)609 if (reg->nlportid != nlportid)
@@ -615,7 +616,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 6 unmodified lines
615 schedule_work(&rdev->mgmt_registrations_update_wk);616 schedule_work(&rdev->mgmt_registrations_update_wk);
616 }617 }
617 618
618 spin_unlock_bh(&wdev->mgmt_registrations_lock);619 spin_unlock_bh(&rdev->mgmt_registrations_lock);
619 620
620 if (nlportid && rdev->crit_proto_nlportid == nlportid) {621 if (nlportid && rdev->crit_proto_nlportid == nlportid) {
621 rdev->crit_proto_nlportid = 0;622 rdev->crit_proto_nlportid = 0;
@@ -628,15 +629,16 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 6 unmodified lines
628 629
629void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)630void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
630{631{
632 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
631 struct cfg80211_mgmt_registration *reg, *tmp;633 struct cfg80211_mgmt_registration *reg, *tmp;
632 634
633 spin_lock_bh(&wdev->mgmt_registrations_lock);635 spin_lock_bh(&rdev->mgmt_registrations_lock);
634 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {636 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
635 list_del(&reg->list);637 list_del(&reg->list);
636 kfree(reg);638 kfree(reg);
637 }639 }
638 wdev->mgmt_registrations_need_update = 1;640 wdev->mgmt_registrations_need_update = 1;
639 spin_unlock_bh(&wdev->mgmt_registrations_lock);641 spin_unlock_bh(&rdev->mgmt_registrations_lock);
640 642
641 cfg80211_mgmt_registrations_update(wdev);643 cfg80211_mgmt_registrations_update(wdev);
642}644}
@@ -784,7 +786,7 @@ bool cfg80211_rx_mgmt_khz(struct wireless_dev *wdev, int freq, int sig_dbm, · 141 unmodified lines
784 data = buf + ieee80211_hdrlen(mgmt->frame_control);786 data = buf + ieee80211_hdrlen(mgmt->frame_control);
785 data_len = len - ieee80211_hdrlen(mgmt->frame_control);787 data_len = len - ieee80211_hdrlen(mgmt->frame_control);
786 788
787 spin_lock_bh(&wdev->mgmt_registrations_lock);789 spin_lock_bh(&rdev->mgmt_registrations_lock);
788 790
789 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {791 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
790 if (reg->frame_type != ftype)792 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
808 break;810 break;
809 }811 }
810 812
811 spin_unlock_bh(&wdev->mgmt_registrations_lock);813 spin_unlock_bh(&rdev->mgmt_registrations_lock);
812 814
813 trace_cfg80211_return_bool(result);815 trace_cfg80211_return_bool(result);
814 return result;816 return result;
net/wireless/util.c+7−7
@@ -1028,14 +1028,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 1027 unmodified lines
1028 !(rdev->wiphy.interface_modes & (1 << ntype)))1028 !(rdev->wiphy.interface_modes & (1 << ntype)))
1029 return -EOPNOTSUPP;1029 return -EOPNOTSUPP;
1030 1030
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
1038 if (ntype != otype) {1031 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
1039 dev->ieee80211_ptr->use_4addr = false;1039 dev->ieee80211_ptr->use_4addr = false;
1040 dev->ieee80211_ptr->mesh_id_up_len = 0;1040 dev->ieee80211_ptr->mesh_id_up_len = 0;
1041 wdev_lock(dev->ieee80211_ptr);1041 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