From 585eb0d6c8bf5ec2016f245c6f5c5b60a14ec074 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Nov 2024 11:21:02 +0100 Subject: [PATCH] mac80211: backport some upstream fixes Fix various issues, including potential crashes Signed-off-by: Felix Fietkau (cherry picked from commit 53eab6198bf87d12055409bc4a38d58b68291b2f) --- ...x-vif-addr-when-switching-from-monit.patch | 63 ++++++++ ...x-incorrect-timing-to-initialize-sta.patch | 32 ++++ ...ee80211_i-Fix-memory-corruption-bug-.patch | 53 +++++++ ...ix-user-power-when-emulating-chanctx.patch | 24 +++ ...80211-Add-wiphy_delayed_work_pending.patch | 83 ++++++++++ ...nvert-color-collision-detection-to-w.patch | 148 ++++++++++++++++++ 6 files changed, 403 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/361-wifi-mac80211-fix-vif-addr-when-switching-from-monit.patch create mode 100644 package/kernel/mac80211/patches/subsys/362-wifi-mac80211-fix-incorrect-timing-to-initialize-sta.patch create mode 100644 package/kernel/mac80211/patches/subsys/363-wifi-mac80211-ieee80211_i-Fix-memory-corruption-bug-.patch create mode 100644 package/kernel/mac80211/patches/subsys/364-mac80211-fix-user-power-when-emulating-chanctx.patch create mode 100644 package/kernel/mac80211/patches/subsys/365-wifi-cfg80211-Add-wiphy_delayed_work_pending.patch create mode 100644 package/kernel/mac80211/patches/subsys/366-wifi-mac80211-Convert-color-collision-detection-to-w.patch diff --git a/package/kernel/mac80211/patches/subsys/361-wifi-mac80211-fix-vif-addr-when-switching-from-monit.patch b/package/kernel/mac80211/patches/subsys/361-wifi-mac80211-fix-vif-addr-when-switching-from-monit.patch new file mode 100644 index 0000000000..f4cfc95aa3 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/361-wifi-mac80211-fix-vif-addr-when-switching-from-monit.patch @@ -0,0 +1,63 @@ +From: Felix Fietkau +Date: Fri, 15 Nov 2024 12:28:43 +0100 +Subject: [PATCH] wifi: mac80211: fix vif addr when switching from monitor + to station + +Since adding support for opting out of virtual monitor support, a zero vif +addr was used to indicate passive vs active monitor to the driver. +This would break the vif->addr when changing the netdev mac address before +switching the interface from monitor to sta mode. +Fix the regression by adding a separate flag to indicate whether vif->addr +is valid. + +Reported-by: syzbot+9ea265d998de25ac6a46@syzkaller.appspotmail.com +Fixes: 9d40f7e32774 ("wifi: mac80211: add flag to opt out of virtual monitor support") +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1972,6 +1972,8 @@ enum ieee80211_neg_ttlm_res { + * @neg_ttlm: negotiated TID to link mapping info. + * see &struct ieee80211_neg_ttlm. + * @addr: address of this interface ++ * @addr_valid: indicates if the address is actively used. Set to false for ++ * passive monitor interfaces, true in all other cases. + * @p2p: indicates whether this AP or STA interface is a p2p + * interface, i.e. a GO or p2p-sta respectively + * @netdev_features: tx netdev features supported by the hardware for this +@@ -2011,6 +2013,7 @@ struct ieee80211_vif { + u16 valid_links, active_links, dormant_links, suspended_links; + struct ieee80211_neg_ttlm neg_ttlm; + u8 addr[ETH_ALEN] __aligned(2); ++ bool addr_valid; + bool p2p; + + u8 cab_queue; +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -279,13 +279,8 @@ static int _ieee80211_change_mac(struct + ret = eth_mac_addr(sdata->dev, sa); + + if (ret == 0) { +- if (check_dup) { +- memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); +- ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr); +- } else { +- memset(sdata->vif.addr, 0, ETH_ALEN); +- memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN); +- } ++ memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); ++ ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr); + } + + /* Regardless of eth_mac_addr() return we still want to add the +@@ -1324,6 +1319,8 @@ int ieee80211_do_open(struct wireless_de + } + } + ++ sdata->vif.addr_valid = sdata->vif.type != NL80211_IFTYPE_MONITOR || ++ (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE); + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + /* no need to tell driver, but set carrier and chanctx */ diff --git a/package/kernel/mac80211/patches/subsys/362-wifi-mac80211-fix-incorrect-timing-to-initialize-sta.patch b/package/kernel/mac80211/patches/subsys/362-wifi-mac80211-fix-incorrect-timing-to-initialize-sta.patch new file mode 100644 index 0000000000..94e51afd85 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/362-wifi-mac80211-fix-incorrect-timing-to-initialize-sta.patch @@ -0,0 +1,32 @@ +From: Benjamin Lin +Date: Mon, 18 Nov 2024 16:07:22 +0800 +Subject: [PATCH] wifi: mac80211: fix incorrect timing to initialize + station NSS capability + +Station's spatial streaming capability should be initialized before +handling VHT OMN, because the handling requires the capability information. + +Fixes: a8bca3e9371d ("wifi: mac80211: track capability/opmode NSS separately") +Signed-off-by: Benjamin Lin +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1914,6 +1914,8 @@ static int sta_link_apply_parameters(str + params->eht_capa_len, + link_sta); + ++ ieee80211_sta_init_nss(link_sta); ++ + if (params->opmode_notif_used) { + /* returned value is only needed for rc update, but the + * rc isn't initialized here yet, so ignore it +@@ -1923,8 +1925,6 @@ static int sta_link_apply_parameters(str + sband->band); + } + +- ieee80211_sta_init_nss(link_sta); +- + return 0; + } + diff --git a/package/kernel/mac80211/patches/subsys/363-wifi-mac80211-ieee80211_i-Fix-memory-corruption-bug-.patch b/package/kernel/mac80211/patches/subsys/363-wifi-mac80211-ieee80211_i-Fix-memory-corruption-bug-.patch new file mode 100644 index 0000000000..dcdb89cd4a --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/363-wifi-mac80211-ieee80211_i-Fix-memory-corruption-bug-.patch @@ -0,0 +1,53 @@ +From: "Gustavo A. R. Silva" +Date: Fri, 25 Oct 2024 16:05:50 -0600 +Subject: [PATCH] wifi: mac80211: ieee80211_i: Fix memory corruption bug in + struct ieee80211_chanctx + +Move the `struct ieee80211_chanctx_conf conf` to the end of +`struct ieee80211_chanctx` and fix a memory corruption bug +triggered e.g. in `hwsim_set_chanctx_magic()`: `radar_detected` +is being overwritten when `cp->magic = HWSIM_CHANCTX_MAGIC;` +See the function call sequence below: + +drv_add_chanctx(... struct ieee80211_chanctx *ctx) -> + local->ops->add_chanctx(&local->hw, &ctx->conf) -> + mac80211_hwsim_add_chanctx(... struct ieee80211_chanctx_conf *ctx) -> + hwsim_set_chanctx_magic(ctx) + +This also happens in a number of other drivers. + +Also, add a code comment to try to prevent people from introducing +new members after `struct ieee80211_chanctx_conf conf`. Notice that +`struct ieee80211_chanctx_conf` is a flexible structure --a structure +that contains a flexible-array member, so it should always be at +the end of any other containing structures. + +This change also fixes 50 of the following warnings: + +net/mac80211/ieee80211_i.h:895:39: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] + +-Wflex-array-member-not-at-end was introduced in GCC-14, and we are +getting ready to enable it, globally. + +Fixes: bca8bc0399ac ("wifi: mac80211: handle ieee80211_radar_detected() for MLO") +Signed-off-by: Gustavo A. R. Silva +Link: https://patch.msgid.link/ZxwWPrncTeSi1UTq@kspp +[also refer to other drivers in commit message] +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -894,9 +894,10 @@ struct ieee80211_chanctx { + /* temporary data for search algorithm etc. */ + struct ieee80211_chan_req req; + +- struct ieee80211_chanctx_conf conf; +- + bool radar_detected; ++ ++ /* MUST be last - ends in a flexible-array member. */ ++ struct ieee80211_chanctx_conf conf; + }; + + struct mac80211_qos_map { diff --git a/package/kernel/mac80211/patches/subsys/364-mac80211-fix-user-power-when-emulating-chanctx.patch b/package/kernel/mac80211/patches/subsys/364-mac80211-fix-user-power-when-emulating-chanctx.patch new file mode 100644 index 0000000000..15db2c54e4 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/364-mac80211-fix-user-power-when-emulating-chanctx.patch @@ -0,0 +1,24 @@ +From: Ben Greear +Date: Thu, 10 Oct 2024 13:39:54 -0700 +Subject: [PATCH] mac80211: fix user-power when emulating chanctx + +ieee80211_calc_hw_conf_chan was ignoring the configured +user_txpower. If it is set, use it to potentially decrease +txpower as requested. + +Signed-off-by: Ben Greear +Link: https://patch.msgid.link/20241010203954.1219686-1-greearb@candelatech.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -167,6 +167,8 @@ static u32 ieee80211_calc_hw_conf_chan(s + } + + power = ieee80211_chandef_max_power(&chandef); ++ if (local->user_power_level != IEEE80211_UNSET_POWER_LEVEL) ++ power = min(local->user_power_level, power); + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { diff --git a/package/kernel/mac80211/patches/subsys/365-wifi-cfg80211-Add-wiphy_delayed_work_pending.patch b/package/kernel/mac80211/patches/subsys/365-wifi-cfg80211-Add-wiphy_delayed_work_pending.patch new file mode 100644 index 0000000000..981cc2433b --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/365-wifi-cfg80211-Add-wiphy_delayed_work_pending.patch @@ -0,0 +1,83 @@ +From: Remi Pommarel +Date: Tue, 24 Sep 2024 21:28:04 +0200 +Subject: [PATCH] wifi: cfg80211: Add wiphy_delayed_work_pending() + +Add wiphy_delayed_work_pending() to check if any delayed work timer is +pending, that can be used to be sure that wiphy_delayed_work_queue() +won't postpone an already pending delayed work. + +Signed-off-by: Remi Pommarel +Link: https://patch.msgid.link/20240924192805.13859-2-repk@triplefau.lt +[fix return value kernel-doc] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6141,6 +6141,50 @@ void wiphy_delayed_work_flush(struct wip + struct wiphy_delayed_work *dwork); + + /** ++ * wiphy_delayed_work_pending - Find out whether a wiphy delayable ++ * work item is currently pending. ++ * ++ * @wiphy: the wiphy, for debug purposes ++ * @dwork: the delayed work in question ++ * ++ * Return: true if timer is pending, false otherwise ++ * ++ * How wiphy_delayed_work_queue() works is by setting a timer which ++ * when it expires calls wiphy_work_queue() to queue the wiphy work. ++ * Because wiphy_delayed_work_queue() uses mod_timer(), if it is ++ * called twice and the second call happens before the first call ++ * deadline, the work will rescheduled for the second deadline and ++ * won't run before that. ++ * ++ * wiphy_delayed_work_pending() can be used to detect if calling ++ * wiphy_work_delayed_work_queue() would start a new work schedule ++ * or delayed a previous one. As seen below it cannot be used to ++ * detect precisely if the work has finished to execute nor if it ++ * is currently executing. ++ * ++ * CPU0 CPU1 ++ * wiphy_delayed_work_queue(wk) ++ * mod_timer(wk->timer) ++ * wiphy_delayed_work_pending(wk) -> true ++ * ++ * [...] ++ * expire_timers(wk->timer) ++ * detach_timer(wk->timer) ++ * wiphy_delayed_work_pending(wk) -> false ++ * wk->timer->function() | ++ * wiphy_work_queue(wk) | delayed work pending ++ * list_add_tail() | returns false but ++ * queue_work(cfg80211_wiphy_work) | wk->func() has not ++ * | been run yet ++ * [...] | ++ * cfg80211_wiphy_work() | ++ * wk->func() V ++ * ++ */ ++bool wiphy_delayed_work_pending(struct wiphy *wiphy, ++ struct wiphy_delayed_work *dwork); ++ ++/** + * enum ieee80211_ap_reg_power - regulatory power for an Access Point + * + * @IEEE80211_REG_UNSET_AP: Access Point has no regulatory power mode +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1735,6 +1735,13 @@ void wiphy_delayed_work_flush(struct wip + } + EXPORT_SYMBOL_GPL(wiphy_delayed_work_flush); + ++bool wiphy_delayed_work_pending(struct wiphy *wiphy, ++ struct wiphy_delayed_work *dwork) ++{ ++ return timer_pending(&dwork->timer); ++} ++EXPORT_SYMBOL_GPL(wiphy_delayed_work_pending); ++ + static int __init cfg80211_init(void) + { + int err; diff --git a/package/kernel/mac80211/patches/subsys/366-wifi-mac80211-Convert-color-collision-detection-to-w.patch b/package/kernel/mac80211/patches/subsys/366-wifi-mac80211-Convert-color-collision-detection-to-w.patch new file mode 100644 index 0000000000..ae72441c46 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/366-wifi-mac80211-Convert-color-collision-detection-to-w.patch @@ -0,0 +1,148 @@ +From: Remi Pommarel +Date: Tue, 24 Sep 2024 21:28:05 +0200 +Subject: [PATCH] wifi: mac80211: Convert color collision detection to wiphy + work + +Call to ieee80211_color_collision_detection_work() needs wiphy lock to +be held (see lockdep assert in cfg80211_bss_color_notify()). Not locking +wiphy causes the following lockdep error: + + WARNING: CPU: 2 PID: 42 at net/wireless/nl80211.c:19505 cfg80211_bss_color_notify+0x1a4/0x25c + Modules linked in: + CPU: 2 PID: 42 Comm: kworker/u8:3 Tainted: G W 6.4.0-02327-g36c6cb260481 #1048 + Hardware name: + Workqueue: phy1 ieee80211_color_collision_detection_work + pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : cfg80211_bss_color_notify+0x1a4/0x25c + lr : cfg80211_bss_color_notify+0x1a0/0x25c + sp : ffff000002947d00 + x29: ffff000002947d00 x28: ffff800008e1a000 x27: ffff000002bd4705 + x26: ffff00000d034000 x25: ffff80000903cf40 x24: 0000000000000000 + x23: ffff00000cb70720 x22: 0000000000800000 x21: ffff800008dfb008 + x20: 000000000000008d x19: ffff00000d035fa8 x18: 0000000000000010 + x17: 0000000000000001 x16: 000003564b1ce96a x15: 000d69696d057970 + x14: 000000000000003b x13: 0000000000000001 x12: 0000000000040000 + x11: 0000000000000001 x10: ffff80000978f9c0 x9 : ffff0000028d3174 + x8 : ffff800008e30000 x7 : 0000000000000000 x6 : 0000000000000028 + x5 : 000000000002f498 x4 : ffff00000d034a80 x3 : 0000000000800000 + x2 : ffff800016143000 x1 : 0000000000000000 x0 : 0000000000000000 + Call trace: + cfg80211_bss_color_notify+0x1a4/0x25c + ieee80211_color_collision_detection_work+0x20/0x118 + process_one_work+0x294/0x554 + worker_thread+0x70/0x440 + kthread+0xf4/0xf8 + ret_from_fork+0x10/0x20 + irq event stamp: 77372 + hardirqs last enabled at (77371): [] _raw_spin_unlock_irq+0x2c/0x4c + hardirqs last disabled at (77372): [] el1_dbg+0x20/0x48 + softirqs last enabled at (77350): [] batadv_send_outstanding_bcast_packet+0xb8/0x120 + softirqs last disabled at (77348): [] batadv_send_outstanding_bcast_packet+0x80/0x120 + +The wiphy lock cannot be taken directly from color collision detection +delayed work (ieee80211_color_collision_detection_work()) because this +work is cancel_delayed_work_sync() under this wiphy lock causing a +potential deadlock( see [0] for details). + +To fix that ieee80211_color_collision_detection_work() could be +converted to a wiphy work and cancel_delayed_work_sync() can be simply +replaced by wiphy_delayed_work_cancel() serving the same purpose under +wiphy lock. + +This could potentially fix [1]. + +[0]: https://lore.kernel.org/linux-wireless/D4A40Q44OAY2.W3SIF6UEPBUN@freebox.fr/ +[1]: https://lore.kernel.org/lkml/000000000000612f290618eee3e5@google.com/ + +Reported-by: Nicolas Escande +Signed-off-by: Remi Pommarel +Link: https://patch.msgid.link/20240924192805.13859-3-repk@triplefau.lt +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4836,12 +4836,12 @@ void ieee80211_color_change_finalize_wor + ieee80211_color_change_finalize(link); + } + +-void ieee80211_color_collision_detection_work(struct work_struct *work) ++void ieee80211_color_collision_detection_work(struct wiphy *wiphy, ++ struct wiphy_work *work) + { +- struct delayed_work *delayed_work = to_delayed_work(work); + struct ieee80211_link_data *link = +- container_of(delayed_work, struct ieee80211_link_data, +- color_collision_detect_work); ++ container_of(work, struct ieee80211_link_data, ++ color_collision_detect_work.work); + struct ieee80211_sub_if_data *sdata = link->sdata; + + cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap, +@@ -4894,7 +4894,8 @@ ieee80211_obss_color_collision_notify(st + return; + } + +- if (delayed_work_pending(&link->color_collision_detect_work)) { ++ if (wiphy_delayed_work_pending(sdata->local->hw.wiphy, ++ &link->color_collision_detect_work)) { + rcu_read_unlock(); + return; + } +@@ -4903,9 +4904,9 @@ ieee80211_obss_color_collision_notify(st + /* queue the color collision detection event every 500 ms in order to + * avoid sending too much netlink messages to userspace. + */ +- ieee80211_queue_delayed_work(&sdata->local->hw, +- &link->color_collision_detect_work, +- msecs_to_jiffies(500)); ++ wiphy_delayed_work_queue(sdata->local->hw.wiphy, ++ &link->color_collision_detect_work, ++ msecs_to_jiffies(500)); + + rcu_read_unlock(); + } +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1056,7 +1056,7 @@ struct ieee80211_link_data { + } csa; + + struct wiphy_work color_change_finalize_work; +- struct delayed_work color_collision_detect_work; ++ struct wiphy_delayed_work color_collision_detect_work; + u64 color_bitmap; + + /* context reservation -- protected with wiphy mutex */ +@@ -2010,7 +2010,8 @@ int ieee80211_channel_switch(struct wiph + /* color change handling */ + void ieee80211_color_change_finalize_work(struct wiphy *wiphy, + struct wiphy_work *work); +-void ieee80211_color_collision_detection_work(struct work_struct *work); ++void ieee80211_color_collision_detection_work(struct wiphy *wiphy, ++ struct wiphy_work *work); + + /* interface handling */ + #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -41,8 +41,8 @@ void ieee80211_link_init(struct ieee8021 + ieee80211_csa_finalize_work); + wiphy_work_init(&link->color_change_finalize_work, + ieee80211_color_change_finalize_work); +- INIT_DELAYED_WORK(&link->color_collision_detect_work, +- ieee80211_color_collision_detection_work); ++ wiphy_delayed_work_init(&link->color_collision_detect_work, ++ ieee80211_color_collision_detection_work); + INIT_LIST_HEAD(&link->assigned_chanctx_list); + INIT_LIST_HEAD(&link->reserved_chanctx_list); + wiphy_delayed_work_init(&link->dfs_cac_timer_work, +@@ -72,7 +72,8 @@ void ieee80211_link_stop(struct ieee8021 + if (link->sdata->vif.type == NL80211_IFTYPE_STATION) + ieee80211_mgd_stop_link(link); + +- cancel_delayed_work_sync(&link->color_collision_detect_work); ++ wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy, ++ &link->color_collision_detect_work); + wiphy_work_cancel(link->sdata->local->hw.wiphy, + &link->color_change_finalize_work); + wiphy_work_cancel(link->sdata->local->hw.wiphy, -- 2.30.2