iwlwifi: add bad length check for WEP keys
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 12 Jun 2008 01:47:09 +0000 (09:47 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Sat, 14 Jun 2008 16:18:08 +0000 (12:18 -0400)
This patch adds a check for bad length in set key flow. This solves the
Oops reported by Thomas Backlund, Joonwoo Park and Ian Schram.
It also adds some debug printing that can be useful.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-sta.c

index a093f5b83cb6785eb516584ac61684ed4e96540b..b58f79626e10357dd38e29180be1b229f2085f17 100644 (file)
@@ -1002,6 +1002,7 @@ struct iwl_wep_cmd {
 #define WEP_KEY_WEP_TYPE 1
 #define WEP_KEYS_MAX 4
 #define WEP_INVALID_OFFSET 0xff
+#define WEP_KEY_LEN_64 5
 #define WEP_KEY_LEN_128 13
 
 /******************************************************************************
index b3caed487f03b1a910f953acc114c6c68f7c6061..3e257cfb44a2ada6f00325004e9d9d5fa3ebcd9b 100644 (file)
@@ -488,6 +488,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
        priv->default_wep_key--;
        memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
        ret = iwl_send_static_wepkey_cmd(priv, 1);
+       IWL_DEBUG_WEP("Remove default WEP key: idx=%d ret=%d\n",
+                     keyconf->keyidx, ret);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        return ret;
@@ -500,6 +502,12 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
        int ret;
        unsigned long flags;
 
+       if (keyconf->keylen != WEP_KEY_LEN_128 &&
+           keyconf->keylen != WEP_KEY_LEN_64) {
+               IWL_DEBUG_WEP("Bad WEP key length %d\n", keyconf->keylen);
+               return -EINVAL;
+       }
+
        keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
        keyconf->hw_key_idx = HW_KEY_DEFAULT;
        priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
@@ -516,6 +524,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
                                                        keyconf->keylen);
 
        ret = iwl_send_static_wepkey_cmd(priv, 0);
+       IWL_DEBUG_WEP("Set default WEP key: len=%d idx=%d ret=%d\n",
+               keyconf->keylen, keyconf->keyidx, ret);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        return ret;
@@ -662,6 +672,9 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
        key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
        keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
 
+       IWL_DEBUG_WEP("Remove dynamic key: idx=%d sta=%d\n",
+                     keyconf->keyidx, sta_id);
+
        if (keyconf->keyidx != keyidx) {
                /* We need to remove a key with index different that the one
                 * in the uCode. This means that the key we need to remove has
@@ -686,7 +699,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
        priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
        priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
-       IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
        ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
        return ret;
@@ -716,6 +728,10 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
                ret = -EINVAL;
        }
 
+       IWL_DEBUG_WEP("Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
+                     keyconf->alg, keyconf->keylen, keyconf->keyidx,
+                     sta_id, ret);
+
        return ret;
 }
 EXPORT_SYMBOL(iwl_set_dynamic_key);