From 002edb6303c5a3f8a21cc2373d21a340c9c5328d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 Mar 2019 12:21:27 +0200 Subject: [PATCH] Fix AP MLME in driver handling of FT and SA Query Action frames hostapd_action_rx() was pointing at incorrect field (Action vs. Category) for the wpa_ft_action_rx() call and the length check for SA Query Action frames. This resulted in those frames getting dropped as invalid (FT) or ignored as truncated (SA Query). Fix this by pointing to the correct place at the beginning of the frame body. This issue had a long history. These were broken during cleanup in commit dbfb8e82ff69 ("Remove unnecessary EVENT_RX_ACTION") which actually fixed the initial reason for the error accidentally. It was just that that error was needed to cancel out another earlier error.. One of the errors came from misuse of the EVENT_RX_ACTION API in commit deca6eff7441 ("atheros: Add new IEEE 802.11r driver_ops"). That pointed struct rx_action data/len to cover the Action frame from the Category field to the end of the frame body while the API was documented to cover Action field to the end of the frame body. This error was cancelled by another error in commit 88b32a99d308 ("FT: Add FT AP support for drivers that manage MLME internally") that called wpa_ft_action_rx() with the struct rx_action::data field as the second argument. That argument needs to point to the Category field, but that struct rx_action field was supposed to point to the Action field. Number of the Action frame handlers added into hostapd_action_rx() had been fixed more or less accidentally after this in various other commits, but the FT and SA Query handlers had ended up maintaining the incorrect operations. This is now fixing those. This seems to fix at least some cases of FT-over-DS with drivers that use driver-based AP MLME. Such drivers might use internal SA Query processing, so it is not clear whether that part actually fixes any real issues. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index e0c85cae6..1c47309f1 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1085,7 +1085,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd, if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1) return; - plen = drv_mgmt->frame_len - IEEE80211_HDRLEN - 1; + plen = drv_mgmt->frame_len - IEEE80211_HDRLEN; mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; fc = le_to_host16(mgmt->frame_control); @@ -1105,9 +1105,8 @@ static void hostapd_action_rx(struct hostapd_data *hapd, } #ifdef CONFIG_IEEE80211R_AP if (mgmt->u.action.category == WLAN_ACTION_FT) { - const u8 *payload = drv_mgmt->frame + 24 + 1; - - wpa_ft_action_rx(sta->wpa_sm, payload, plen); + wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, plen); + return; } #endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_IEEE80211W @@ -1127,7 +1126,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd, } #endif /* CONFIG_FST */ #ifdef CONFIG_DPP - if (plen >= 1 + 4 && + if (plen >= 2 + 4 && mgmt->u.action.u.vs_public_action.action == WLAN_PA_VENDOR_SPECIFIC && WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==