Vulnerability: In the Linux kernel before 3.4, a buffer overflow occurs in drivers/net/wireless/iwlwifi/iwl-agn-sta.c, which will cause at least memory corruption.
Vulnerability ID: CVE-2012-6712
CWE: CWE-119
Severity score: 6.4
Project: https://github.com/torvalds/linux
Published: 2019-07-27
File: drivers/net/wireless/iwlwifi/iwl-agn-sta.c
Commit message: iwlwifi: Sanity check for sta_id

On my testing, I saw some strange behavior

[  421.739708] iwlwifi 0000:01:00.0: ACTIVATE a non DRIVER active station id 148 addr 00:00:00:00:00:00
[  421.739719] iwlwifi 0000:01:00.0: iwl_sta_ucode_activate Added STA id 148 addr 00:00:00:00:00:00 to uCode

not sure how it happen, but adding the sanity check to prevent memory
corruption

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Commit author: Wey-Yi Guy

Vulnerable version (before fix):
 #include "iwl-trans.h"  /* priv->shrd->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) {  	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) 		IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u " 			"addr %pM\n", static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) 		IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", 				sta_id, priv->stations[sta_id].sta.sta.addr); 	} }  static int iwl_process_add_sta_resp(struct iwl_priv *priv, static int iwl_process_add_sta_resp(struct iwl_priv *priv, 	switch (pkt->u.add_sta.status) { 	case ADD_STA_SUCCESS_MSK: 		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); 		iwl_sta_ucode_activate(priv, sta_id); 		ret = 0; 		break; 	case ADD_STA_NO_ROOM_IN_TABLE: 		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",

Fixed version (after fix):
 #include "iwl-trans.h"  /* priv->shrd->sta_lock must be held */ static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { 	if (sta_id >= IWLAGN_STATION_COUNT) { 		IWL_ERR(priv, "invalid sta_id %u", sta_id); 		return -EINVAL; 	} 	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) 		IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u " 			"addr %pM\n", static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) 		IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", 				sta_id, priv->stations[sta_id].sta.sta.addr); 	} 	return 0; }  static int iwl_process_add_sta_resp(struct iwl_priv *priv, static int iwl_process_add_sta_resp(struct iwl_priv *priv, 	switch (pkt->u.add_sta.status) { 	case ADD_STA_SUCCESS_MSK: 		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); 		ret = iwl_sta_ucode_activate(priv, sta_id); 		break; 	case ADD_STA_NO_ROOM_IN_TABLE: 		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",

Patch:
patch: @@ -35,9 +35,12 @@
 #include "iwl-trans.h"
 
 /* priv->shrd->sta_lock must be held */
-static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 {
-
+	if (sta_id >= IWLAGN_STATION_COUNT) {
+		IWL_ERR(priv, "invalid sta_id %u", sta_id);
+		return -EINVAL;
+	}
 	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
 		IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u "
 			"addr %pM\n",
@@ -53,6 +56,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 		IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
 				sta_id, priv->stations[sta_id].sta.sta.addr);
 	}
+	return 0;
 }
 
 static int iwl_process_add_sta_resp(struct iwl_priv *priv,
@@ -77,8 +81,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
 	switch (pkt->u.add_sta.status) {
 	case ADD_STA_SUCCESS_MSK:
 		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
-		iwl_sta_ucode_activate(priv, sta_id);
-		ret = 0;
+		ret = iwl_sta_ucode_activate(priv, sta_id);
 		break;
 	case ADD_STA_NO_ROOM_IN_TABLE:
 		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
path: drivers/net/wireless/iwlwifi/iwl-agn-sta.c