CVE-2012-6712: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: 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.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 9.8
Published: 2019-07-27T22:15Z
Repository: https://github.com/torvalds/linux
Language: C
Files changed: drivers/net/wireless/iwlwifi/iwl-agn-sta.c
Commit date: 2012-01-24 14:08:35 -0500
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>

Diff: diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 7353826095f11..8d4353a42568f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -33,13 +33,16 @@
 #include "iwl-core.h"
 #include "iwl-agn.h"
 #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",
 			sta_id, priv->stations[sta_id].sta.sta.addr);
 
@@ -51,10 +54,11 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 	} else {
 		priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
 		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,
 				    struct iwl_addsta_cmd *addsta,
 				    struct iwl_rx_packet *pkt)
@@ -75,12 +79,11 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
 	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
 
 	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",
 			sta_id);
 		break;

Vulnerable code: static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)

		iwl_sta_ucode_activate(priv, sta_id);
		ret = 0;
Fixed code: 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;
	}
	return 0;
		ret = iwl_sta_ucode_activate(priv, sta_id);