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 dbfb8e82ff ("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
deca6eff74 ("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 88b32a99d3 ("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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-03-09 12:21:27 +02:00
parent 0defc42a49
commit 002edb6303

View file

@ -1085,7 +1085,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1) if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1)
return; return;
plen = drv_mgmt->frame_len - IEEE80211_HDRLEN - 1; plen = drv_mgmt->frame_len - IEEE80211_HDRLEN;
mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
fc = le_to_host16(mgmt->frame_control); fc = le_to_host16(mgmt->frame_control);
@ -1105,9 +1105,8 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
} }
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
if (mgmt->u.action.category == WLAN_ACTION_FT) { if (mgmt->u.action.category == WLAN_ACTION_FT) {
const u8 *payload = drv_mgmt->frame + 24 + 1; wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, plen);
return;
wpa_ft_action_rx(sta->wpa_sm, payload, plen);
} }
#endif /* CONFIG_IEEE80211R_AP */ #endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W #ifdef CONFIG_IEEE80211W
@ -1127,7 +1126,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
} }
#endif /* CONFIG_FST */ #endif /* CONFIG_FST */
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
if (plen >= 1 + 4 && if (plen >= 2 + 4 &&
mgmt->u.action.u.vs_public_action.action == mgmt->u.action.u.vs_public_action.action ==
WLAN_PA_VENDOR_SPECIFIC && WLAN_PA_VENDOR_SPECIFIC &&
WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) == WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==