116 lines
4.2 KiB
Diff
116 lines
4.2 KiB
Diff
|
From f35978844e2eea1b2a6d4a2a6445d66528fc7a06 Mon Sep 17 00:00:00 2001
|
||
|
From: Sara Sharon <sara.sharon@intel.com>
|
||
|
Date: Tue, 29 Mar 2016 10:56:57 +0300
|
||
|
Subject: [PATCH] iwlwifi: mvm: fix security bug in PN checking
|
||
|
|
||
|
A previous patch allowed the same PN for packets originating from the
|
||
|
same AMSDU by copying PN only for the last packet in the series.
|
||
|
|
||
|
This however is bogus since we cannot assume the last frame will be
|
||
|
received on the same queue, and if it is received on a different ueue
|
||
|
we will end up not incrementing the PN and possibly let the next
|
||
|
packet to have the same PN and pass through.
|
||
|
|
||
|
Change the logic instead to driver explicitly indicate for the second
|
||
|
sub frame and on to be allowed to have the same PN as the first
|
||
|
subframe. Indicate it to mac80211 as well for the fallback queue.
|
||
|
|
||
|
Fixes: f1ae02b186d9 ("iwlwifi: mvm: allow same PN for de-aggregated AMSDU")
|
||
|
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
|
||
|
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
|
||
|
---
|
||
|
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 39 ++++++++++++++-------------
|
||
|
1 file changed, 20 insertions(+), 19 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
|
||
|
index 71d6660c48e1..4a4ccfd11e5b 100644
|
||
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
|
||
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
|
||
|
@@ -71,6 +71,7 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||
|
struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
|
||
|
struct iwl_mvm_key_pn *ptk_pn;
|
||
|
+ int res;
|
||
|
u8 tid, keyidx;
|
||
|
u8 pn[IEEE80211_CCMP_PN_LEN];
|
||
|
u8 *extiv;
|
||
|
@@ -127,12 +128,13 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||
|
pn[4] = extiv[1];
|
||
|
pn[5] = extiv[0];
|
||
|
|
||
|
- if (memcmp(pn, ptk_pn->q[queue].pn[tid],
|
||
|
- IEEE80211_CCMP_PN_LEN) <= 0)
|
||
|
+ res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);
|
||
|
+ if (res < 0)
|
||
|
+ return -1;
|
||
|
+ if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN))
|
||
|
return -1;
|
||
|
|
||
|
- if (!(stats->flag & RX_FLAG_AMSDU_MORE))
|
||
|
- memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
|
||
|
+ memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
|
||
|
stats->flag |= RX_FLAG_PN_VALIDATED;
|
||
|
|
||
|
return 0;
|
||
|
@@ -314,28 +316,21 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * returns true if a packet outside BA session is a duplicate and
|
||
|
- * should be dropped
|
||
|
+ * returns true if a packet is a duplicate and should be dropped.
|
||
|
+ * Updates AMSDU PN tracking info
|
||
|
*/
|
||
|
-static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue,
|
||
|
- struct ieee80211_rx_status *rx_status,
|
||
|
- struct ieee80211_hdr *hdr,
|
||
|
- struct iwl_rx_mpdu_desc *desc)
|
||
|
+static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
||
|
+ struct ieee80211_rx_status *rx_status,
|
||
|
+ struct ieee80211_hdr *hdr,
|
||
|
+ struct iwl_rx_mpdu_desc *desc)
|
||
|
{
|
||
|
struct iwl_mvm_sta *mvm_sta;
|
||
|
struct iwl_mvm_rxq_dup_data *dup_data;
|
||
|
- u8 baid, tid, sub_frame_idx;
|
||
|
+ u8 tid, sub_frame_idx;
|
||
|
|
||
|
if (WARN_ON(IS_ERR_OR_NULL(sta)))
|
||
|
return false;
|
||
|
|
||
|
- baid = (le32_to_cpu(desc->reorder_data) &
|
||
|
- IWL_RX_MPDU_REORDER_BAID_MASK) >>
|
||
|
- IWL_RX_MPDU_REORDER_BAID_SHIFT;
|
||
|
-
|
||
|
- if (baid != IWL_RX_REORDER_DATA_INVALID_BAID)
|
||
|
- return false;
|
||
|
-
|
||
|
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||
|
dup_data = &mvm_sta->dup_data[queue];
|
||
|
|
||
|
@@ -365,6 +360,12 @@ static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue,
|
||
|
dup_data->last_sub_frame[tid] >= sub_frame_idx))
|
||
|
return true;
|
||
|
|
||
|
+ /* Allow same PN as the first subframe for following sub frames */
|
||
|
+ if (dup_data->last_seq[tid] == hdr->seq_ctrl &&
|
||
|
+ sub_frame_idx > dup_data->last_sub_frame[tid] &&
|
||
|
+ desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU)
|
||
|
+ rx_status->flag |= RX_FLAG_ALLOW_SAME_PN;
|
||
|
+
|
||
|
dup_data->last_seq[tid] = hdr->seq_ctrl;
|
||
|
dup_data->last_sub_frame[tid] = sub_frame_idx;
|
||
|
|
||
|
@@ -981,7 +982,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||
|
if (ieee80211_is_data(hdr->frame_control))
|
||
|
iwl_mvm_rx_csum(sta, skb, desc);
|
||
|
|
||
|
- if (iwl_mvm_is_nonagg_dup(sta, queue, rx_status, hdr, desc)) {
|
||
|
+ if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) {
|
||
|
kfree_skb(skb);
|
||
|
goto out;
|
||
|
}
|
||
|
--
|
||
|
2.15.1
|
||
|
|