OSDN Git Service

iwlwifi: mvm: fix beacon protection checks
authorJohannes Berg <johannes.berg@intel.com>
Fri, 26 Mar 2021 10:57:23 +0000 (12:57 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 6 Apr 2021 10:26:36 +0000 (13:26 +0300)
Unfortunately, since beacon protection isn't fully available
yet, we didn't notice that there are problems with it and
that the replay detection isn't working correctly. We were
relying only on mac80211, since iwl_mvm_rx_crypto() exits
when !ieee80211_has_protected(), which is of course true for
protected (but not encrypted) management frames.

Fix this to properly detect protected (but not encrypted)
management frames and handle them - we continue to only care
about beacons since for others everything can and will be
checked in mac80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Fixes: b1fdc2505abc ("iwlwifi: mvm: advertise BIGTK client support if available")
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20210326125611.23c990843369.I09c262a8f6f9852cc8f513cdcb31a7f8f87dd8af@changeid
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c

index c21736f..af5a6dd 100644 (file)
@@ -272,10 +272,10 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
        rx_status->chain_signal[2] = S8_MIN;
 }
 
-static int iwl_mvm_rx_mgmt_crypto(struct ieee80211_sta *sta,
-                                 struct ieee80211_hdr *hdr,
-                                 struct iwl_rx_mpdu_desc *desc,
-                                 u32 status)
+static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+                               struct ieee80211_hdr *hdr,
+                               struct iwl_rx_mpdu_desc *desc,
+                               u32 status)
 {
        struct iwl_mvm_sta *mvmsta;
        struct iwl_mvm_vif *mvmvif;
@@ -285,6 +285,9 @@ static int iwl_mvm_rx_mgmt_crypto(struct ieee80211_sta *sta,
        u32 len = le16_to_cpu(desc->mpdu_len);
        const u8 *frame = (void *)hdr;
 
+       if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE)
+               return 0;
+
        /*
         * For non-beacon, we don't really care. But beacons may
         * be filtered out, and we thus need the firmware's replay
@@ -356,6 +359,10 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
            IWL_RX_MPDU_STATUS_SEC_UNKNOWN && !mvm->monitor_on)
                return -1;
 
+       if (unlikely(ieee80211_is_mgmt(hdr->frame_control) &&
+                    !ieee80211_has_protected(hdr->frame_control)))
+               return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status);
+
        if (!ieee80211_has_protected(hdr->frame_control) ||
            (status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
            IWL_RX_MPDU_STATUS_SEC_NONE)
@@ -411,7 +418,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                stats->flag |= RX_FLAG_DECRYPTED;
                return 0;
        case RX_MPDU_RES_STATUS_SEC_CMAC_GMAC_ENC:
-               return iwl_mvm_rx_mgmt_crypto(sta, hdr, desc, status);
+               break;
        default:
                /*
                 * Sometimes we can get frames that were not decrypted