From 0c4e73bb83f5a184d7a2bc98aba7ef12d0f5af2f Mon Sep 17 00:00:00 2001 From: stsp Date: Mon, 3 May 2021 08:23:05 +0000 Subject: [PATCH] work around an athn(4) device problem with bogus Michael MIC failures Clients using Tx aggregation against an athn(4) hostap will send block ack request control frames whenever they need to sync their Tx block ack window. athn(4) dropped such frames due to bogus Michael MIC failures reported by the hardware decryption engine. Ignore such failures for control frames in order to fix athn(4) hostap mode against clients which use Tx aggregation. Additionally, only report Michael MIC failures to the net80211 stack if the offending client is actually using TKIP, which would also have prevented the problem since we require CCMP as group cipher in our default configuration. Problem reported and fix tested by kettenis@ --- sys/dev/ic/ar5008.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c index 2b77b0d686d..816a3b09ee2 100644 --- a/sys/dev/ic/ar5008.c +++ b/sys/dev/ic/ar5008.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5008.c,v 1.65 2021/04/15 18:25:43 stsp Exp $ */ +/* $OpenBSD: ar5008.c,v 1.66 2021/05/03 08:23:05 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -865,7 +865,7 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml) struct ieee80211_rxinfo rxi; struct ieee80211_node *ni; struct mbuf *m, *m1; - int error, len; + int error, len, michael_mic_failure = 0; bf = SIMPLEQ_FIRST(&rxq->head); if (__predict_false(bf == NULL)) { /* Should not happen. */ @@ -915,16 +915,12 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml) ic->ic_stats.is_ccmp_dec_errs++; } else if (ds->ds_status8 & AR_RXS8_MICHAEL_ERR) { DPRINTFN(2, ("Michael MIC failure\n")); - /* Report Michael MIC failures to net80211. */ - ic->ic_stats.is_rx_locmicfail++; - ieee80211_michael_mic_failure(ic, 0); - /* - * XXX Check that it is not a control frame - * (invalid MIC failures on valid ctl frames). - */ + michael_mic_failure = 1; + } + if (!michael_mic_failure) { + ifp->if_ierrors++; + goto skip; } - ifp->if_ierrors++; - goto skip; } len = MS(ds->ds_status1, AR_RXS1_DATA_LEN); @@ -978,6 +974,25 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml) wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, wh); + if (michael_mic_failure) { + /* + * Check that it is not a control frame + * (invalid MIC failures on valid ctl frames). + */ + if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL) && + (ic->ic_flags & IEEE80211_F_RSNON) && + (ni->ni_rsncipher == IEEE80211_CIPHER_TKIP || + ni->ni_rsngroupcipher == IEEE80211_CIPHER_TKIP)) { + /* Report Michael MIC failures to net80211. */ + ic->ic_stats.is_rx_locmicfail++; + ieee80211_michael_mic_failure(ic, 0); + ifp->if_ierrors++; + ieee80211_release_node(ic, ni); + m_freem(m); + goto skip; + } + } + /* Remove any HW padding after the 802.11 header. */ if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL)) { u_int hdrlen = ieee80211_get_hdrlen(wh); -- 2.20.1