iwlwifi: prevent read outside array bounds
authorReinette Chatre <reinette.chatre@intel.com>
Thu, 13 Aug 2009 20:30:50 +0000 (13:30 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 20 Aug 2009 15:33:09 +0000 (11:33 -0400)
With EDCA and HCCA we have 16 potential tid values. This is accommodated by
mac80211, but iwlwifi only supports EDCA. With this implementation it is
thus possible for mac80211 to request a tid that will cause iwlwifi to read
outside array bounds. A similar problem exists if traffic is received in an
unsupported category.

We add error checking to catch these situations.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c

index 21331552ff2c5a4563ba8fd51d1ddf210494211a..1bd7cd4dd80907ade69215de3ff9c3de06a96533 100644 (file)
@@ -332,6 +332,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
        } else
                return MAX_TID_COUNT;
 
+       if (unlikely(tid >= TID_MAX_LOAD_COUNT))
+               return MAX_TID_COUNT;
+
        tl = &lq_data->load[tid];
 
        curr_time -= curr_time % TID_ROUND_VALUE;
index 9b76bd41f2149a0f96a443688f3e72b5e9e9e38d..7686fc72eb894c015146c85cbc84f17ac4fc1456 100644 (file)
@@ -745,6 +745,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (ieee80211_is_data_qos(fc)) {
                qc = ieee80211_get_qos_ctl(hdr);
                tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+               if (unlikely(tid >= MAX_TID_COUNT))
+                       goto drop_unlock;
                seq_number = priv->stations[sta_id].tid[tid].seq_number;
                seq_number &= IEEE80211_SCTL_SEQ;
                hdr->seq_ctrl = hdr->seq_ctrl &
@@ -1238,6 +1240,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
                return -EINVAL;
        }
 
+       if (unlikely(tid >= MAX_TID_COUNT))
+               return -EINVAL;
+
        if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
                tx_fifo_id = default_tid_to_tx_fifo[tid];
        else
index e617411d0c5e4a7b439b426d73a6470cbf7c073c..f339c5bd1fdecff5b272cb6461e184bffc5e4d4c 100644 (file)
@@ -544,6 +544,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (ieee80211_is_data_qos(fc)) {
                qc = ieee80211_get_qos_ctl(hdr);
                tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+               if (unlikely(tid >= MAX_TID_COUNT))
+                       goto drop;
                seq_number = priv->stations[sta_id].tid[tid].seq_number &
                                IEEE80211_SCTL_SEQ;
                hdr->seq_ctrl = cpu_to_le16(seq_number) |