]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: don't complete management TX on SAE commit
authorJohannes Berg <johannes.berg@intel.com>
Mon, 9 Jun 2025 18:35:27 +0000 (21:35 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 9 Jul 2025 09:56:45 +0000 (11:56 +0200)
When SAE commit is sent and received in response, there's no
ordering for the SAE confirm messages. As such, don't call
drivers to stop listening on the channel when the confirm
message is still expected.

This fixes an issue if the local confirm is transmitted later
than the AP's confirm, for iwlwifi (and possibly mt76) the
AP's confirm would then get lost since the device isn't on
the channel at the time the AP transmit the confirm.

For iwlwifi at least, this also improves the overall timing
of the authentication handshake (by about 15ms according to
the report), likely since the session protection won't be
aborted and rescheduled.

Note that even before this, mgd_complete_tx() wasn't always
called for each call to mgd_prepare_tx() (e.g. in the case
of WEP key shared authentication), and the current drivers
that have the complete callback don't seem to mind. Document
this as well though.

Reported-by: Jan Hendrik Farr <kernel@jfarr.cc>
Closes: https://lore.kernel.org/all/aB30Ea2kRG24LINR@archlinux/
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250609213232.12691580e140.I3f1d3127acabcd58348a110ab11044213cf147d3@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/mlme.c

index 14a6bd120f2548bd4662b609b88296b59452b318..577fd6a8c372f6cd544db6e74207365b5f358cf3 100644 (file)
@@ -4310,6 +4310,8 @@ struct ieee80211_prep_tx_info {
  * @mgd_complete_tx: Notify the driver that the response frame for a previously
  *     transmitted frame announced with @mgd_prepare_tx was received, the data
  *     is filled similarly to @mgd_prepare_tx though the duration is not used.
+ *     Note that this isn't always called for each mgd_prepare_tx() call, for
+ *     example for SAE the 'confirm' messages can be on the air in any order.
  *
  * @mgd_protect_tdls_discover: Protect a TDLS discovery session. After sending
  *     a TDLS discovery-request, we expect a reply to arrive on the AP's
index aaff7e9c3eb7177a50460e7836a0b2d16e028df4..8b9c132cce3d5d1b22749b52687834a0855c53c1 100644 (file)
@@ -4780,6 +4780,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_prep_tx_info info = {
                .subtype = IEEE80211_STYPE_AUTH,
        };
+       bool sae_need_confirm = false;
 
        lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
@@ -4825,6 +4826,8 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
                                jiffies + IEEE80211_AUTH_WAIT_SAE_RETRY;
                        ifmgd->auth_data->timeout_started = true;
                        run_again(sdata, ifmgd->auth_data->timeout);
+                       if (auth_transaction == 1)
+                               sae_need_confirm = true;
                        goto notify_driver;
                }
 
@@ -4867,6 +4870,9 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
             ifmgd->auth_data->expected_transaction == 2)) {
                if (!ieee80211_mark_sta_auth(sdata))
                        return; /* ignore frame -- wait for timeout */
+       } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
+                  auth_transaction == 1) {
+               sae_need_confirm = true;
        } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
                   auth_transaction == 2) {
                sdata_info(sdata, "SAE peer confirmed\n");
@@ -4875,7 +4881,8 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
 
        cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
 notify_driver:
-       drv_mgd_complete_tx(sdata->local, sdata, &info);
+       if (!sae_need_confirm)
+               drv_mgd_complete_tx(sdata->local, sdata, &info);
 }
 
 #define case_WLAN(type) \