mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 14:49:24 +01:00
ap: Make station removal safer
Replace instances of the ap_del_station() + ap_sta_free()/ap_remove_sta() with calls to ap_station_disconnect to make sure we consistently remove the station from the ap->sta_states queue before using ap_del_station(). ap_del_station() may generate an event to the ap.h API user (e.g. P2P) and this may end up tearing down the AP completely. For that scenario we also don't want ap_sta_free() to access sta->ap so we make sure ap_del_station() performs these cleanup steps so that ap_sta_free() has nothing to do that accesses sta->ap.
This commit is contained in:
parent
97a34e6b4a
commit
2af0166970
28
src/ap.c
28
src/ap.c
@ -251,6 +251,11 @@ static void ap_del_station(struct sta_state *sta, uint16_t reason,
|
||||
sta->rsna = false;
|
||||
}
|
||||
|
||||
if (sta->assoc_resp_cmd_id) {
|
||||
l_genl_family_cancel(ap->nl80211, sta->assoc_resp_cmd_id);
|
||||
sta->assoc_resp_cmd_id = 0;
|
||||
}
|
||||
|
||||
if (sta->gtk_query_cmd_id) {
|
||||
l_genl_family_cancel(ap->nl80211, sta->gtk_query_cmd_id);
|
||||
sta->gtk_query_cmd_id = 0;
|
||||
@ -258,6 +263,10 @@ static void ap_del_station(struct sta_state *sta, uint16_t reason,
|
||||
|
||||
ap_stop_handshake(sta);
|
||||
|
||||
/*
|
||||
* If the event handler tears the AP down, we've made sure above that
|
||||
* a subsequent ap_sta_free(sta) has no need to access sta->ap.
|
||||
*/
|
||||
if (send_event)
|
||||
ap->ops->handle_event(AP_EVENT_STATION_REMOVED, &event_data,
|
||||
ap->user_data);
|
||||
@ -2004,7 +2013,6 @@ static void ap_deauth_cb(const struct mmpdu_header *hdr, const void *body,
|
||||
size_t body_len, int rssi, void *user_data)
|
||||
{
|
||||
struct ap_state *ap = user_data;
|
||||
struct sta_state *sta;
|
||||
const struct mmpdu_deauthentication *deauth = body;
|
||||
const uint8_t *bssid = netdev_get_address(ap->netdev);
|
||||
|
||||
@ -2016,14 +2024,8 @@ static void ap_deauth_cb(const struct mmpdu_header *hdr, const void *body,
|
||||
memcmp(hdr->address_3, bssid, 6))
|
||||
return;
|
||||
|
||||
sta = l_queue_remove_if(ap->sta_states, ap_sta_match_addr,
|
||||
hdr->address_2);
|
||||
if (!sta)
|
||||
return;
|
||||
|
||||
ap_del_station(sta, L_LE16_TO_CPU(deauth->reason_code), false);
|
||||
|
||||
ap_sta_free(sta);
|
||||
ap_station_disconnect(ap, hdr->address_2,
|
||||
L_LE16_TO_CPU(deauth->reason_code));
|
||||
}
|
||||
|
||||
static void do_debug(const char *str, void *user_data)
|
||||
@ -2339,7 +2341,6 @@ cleanup:
|
||||
|
||||
static void ap_handle_del_station(struct ap_state *ap, struct l_genl_msg *msg)
|
||||
{
|
||||
struct sta_state *sta;
|
||||
struct l_genl_attr attr;
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
@ -2366,12 +2367,7 @@ static void ap_handle_del_station(struct ap_state *ap, struct l_genl_msg *msg)
|
||||
}
|
||||
}
|
||||
|
||||
sta = l_queue_find(ap->sta_states, ap_sta_match_addr, mac);
|
||||
if (!sta)
|
||||
return;
|
||||
|
||||
ap_del_station(sta, reason, true);
|
||||
ap_remove_sta(sta);
|
||||
ap_station_disconnect(ap, mac, reason);
|
||||
}
|
||||
|
||||
static void ap_mlme_notify(struct l_genl_msg *msg, void *user_data)
|
||||
|
Loading…
Reference in New Issue
Block a user