Skip to content

Commit

Permalink
mac80211: backport some upstream fixes
Browse files Browse the repository at this point in the history
Fix various issues, including potential crashes

Signed-off-by: Felix Fietkau <[email protected]>
  • Loading branch information
nbd168 committed Nov 18, 2024
1 parent efc0c46 commit 53eab61
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
From: Felix Fietkau <[email protected]>
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: [email protected]
Fixes: 9d40f7e32774 ("wifi: mac80211: add flag to opt out of virtual monitor support")
Signed-off-by: Felix Fietkau <[email protected]>
---

--- 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 */
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
From: Benjamin Lin <[email protected]>
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 <[email protected]>
---

--- 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;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
From: "Gustavo A. R. Silva" <[email protected]>
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 <[email protected]>
Link: https://patch.msgid.link/ZxwWPrncTeSi1UTq@kspp
[also refer to other drivers in commit message]
Signed-off-by: Johannes Berg <[email protected]>
---

--- 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 {
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
From: Ben Greear <[email protected]>
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 <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Johannes Berg <[email protected]>
---

--- 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) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
From: Remi Pommarel <[email protected]>
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 <[email protected]>
Link: https://patch.msgid.link/[email protected]
[fix return value kernel-doc]
Signed-off-by: Johannes Berg <[email protected]>
---

--- 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;
Loading

0 comments on commit 53eab61

Please sign in to comment.