Skip to content

Commit

Permalink
wifi: mac80211: flush the station before moving it to UN-AUTHORIZED s…
Browse files Browse the repository at this point in the history
…tate

We first want to flush the station to make sure we no longer have any
frames being Tx by the station before the station is moved to
un-authorized state. Failing to do that will lead to races: a frame may
be sent after the station's state has been changed.

Since the API clearly states that the driver can't fail the sta_state()
transition down the list of state, we can easily flush the station
first, and only then call the driver's sta_state().

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250306123626.450bc40e8b04.I636ba96843c77f13309c15c9fd6eb0c5a52a7976@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Emmanuel Grumbach authored and Johannes Berg committed Mar 7, 2025
1 parent 1801a94 commit 43e0407
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2023 Intel Corporation
* Copyright (C) 2018-2024 Intel Corporation
*/

#include <linux/module.h>
Expand Down Expand Up @@ -1335,9 +1335,13 @@ static int _sta_info_move_state(struct sta_info *sta,
sta->sta.addr, new_state);

/* notify the driver before the actual changes so it can
* fail the transition
* fail the transition if the state is increasing.
* The driver is required not to fail when the transition
* is decreasing the state, so first, do all the preparation
* work and only then, notify the driver.
*/
if (test_sta_flag(sta, WLAN_STA_INSERTED)) {
if (new_state > sta->sta_state &&
test_sta_flag(sta, WLAN_STA_INSERTED)) {
int err = drv_sta_state(sta->local, sta->sdata, sta,
sta->sta_state, new_state);
if (err)
Expand Down Expand Up @@ -1413,6 +1417,16 @@ static int _sta_info_move_state(struct sta_info *sta,
break;
}

if (new_state < sta->sta_state &&
test_sta_flag(sta, WLAN_STA_INSERTED)) {
int err = drv_sta_state(sta->local, sta->sdata, sta,
sta->sta_state, new_state);

WARN_ONCE(err,
"Driver is not allowed to fail if the sta_state is transitioning down the list: %d\n",
err);
}

sta->sta_state = new_state;

return 0;
Expand Down

0 comments on commit 43e0407

Please sign in to comment.