ath9k: Fix bug in validating received data length for edma
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / ath9k / recv.c
index a0f89a48509e078ff8e252b846d86bdb886723eb..1618f8fe195db4ad783e117baad6b15d4f4bae83 100644 (file)
@@ -823,16 +823,15 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
 
 /* Assumes you've already done the endian to CPU conversion */
 static bool ath9k_rx_accept(struct ath_common *common,
-                           struct sk_buff *skb,
+                           struct ieee80211_hdr *hdr,
                            struct ieee80211_rx_status *rxs,
                            struct ath_rx_status *rx_stats,
                            bool *decrypt_error)
 {
        struct ath_hw *ah = common->ah;
-       struct ieee80211_hdr *hdr;
        __le16 fc;
+       u8 rx_status_len = ah->caps.rx_status_len;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
        fc = hdr->frame_control;
 
        if (!rx_stats->rs_datalen)
@@ -842,7 +841,7 @@ static bool ath9k_rx_accept(struct ath_common *common,
          * we can take a hint that hardware corrupted it, so ignore
          * those frames.
          */
-       if (rx_stats->rs_datalen > common->rx_bufsize)
+       if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
                return false;
 
        /*
@@ -903,8 +902,7 @@ static bool ath9k_rx_accept(struct ath_common *common,
 static int ath9k_process_rate(struct ath_common *common,
                              struct ieee80211_hw *hw,
                              struct ath_rx_status *rx_stats,
-                             struct ieee80211_rx_status *rxs,
-                             struct sk_buff *skb)
+                             struct ieee80211_rx_status *rxs)
 {
        struct ieee80211_supported_band *sband;
        enum ieee80211_band band;
@@ -942,25 +940,21 @@ static int ath9k_process_rate(struct ath_common *common,
         */
        ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
                  "0x%02x using 1 Mbit\n", rx_stats->rs_rate);
-       if ((common->debug_mask & ATH_DBG_XMIT))
-               print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len);
 
        return -EINVAL;
 }
 
 static void ath9k_process_rssi(struct ath_common *common,
                               struct ieee80211_hw *hw,
-                              struct sk_buff *skb,
+                              struct ieee80211_hdr *hdr,
                               struct ath_rx_status *rx_stats)
 {
        struct ath_hw *ah = common->ah;
        struct ieee80211_sta *sta;
-       struct ieee80211_hdr *hdr;
        struct ath_node *an;
        int last_rssi = ATH_RSSI_DUMMY_MARKER;
        __le16 fc;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
        fc = hdr->frame_control;
 
        rcu_read_lock();
@@ -999,7 +993,7 @@ static void ath9k_process_rssi(struct ath_common *common,
  */
 static int ath9k_rx_skb_preprocess(struct ath_common *common,
                                   struct ieee80211_hw *hw,
-                                  struct sk_buff *skb,
+                                  struct ieee80211_hdr *hdr,
                                   struct ath_rx_status *rx_stats,
                                   struct ieee80211_rx_status *rx_status,
                                   bool *decrypt_error)
@@ -1012,12 +1006,12 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
         * everything but the rate is checked here, the rate check is done
         * separately to avoid doing two lookups for a rate for each frame.
         */
-       if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error))
+       if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
                return -EINVAL;
 
-       ath9k_process_rssi(common, hw, skb, rx_stats);
+       ath9k_process_rssi(common, hw, hdr, rx_stats);
 
-       if (ath9k_process_rate(common, hw, rx_stats, rx_status, skb))
+       if (ath9k_process_rate(common, hw, rx_stats, rx_status))
                return -EINVAL;
 
        rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
@@ -1101,6 +1095,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
        enum ath9k_rx_qtype qtype;
        bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
        int dma_type;
+       u8 rx_status_len = ah->caps.rx_status_len;
 
        if (edma)
                dma_type = DMA_BIDIRECTIONAL;
@@ -1128,7 +1123,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                if (!skb)
                        continue;
 
-               hdr = (struct ieee80211_hdr *) skb->data;
+               hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
                rxs =  IEEE80211_SKB_RXCB(skb);
 
                hw = ath_get_virt_hw(sc, hdr);
@@ -1142,7 +1137,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                if (flush)
                        goto requeue;
 
-               retval = ath9k_rx_skb_preprocess(common, hw, skb, &rs,
+               retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
                                                 rxs, &decrypt_error);
                if (retval)
                        goto requeue;