浏览代码

mwifiex: fix invalid memory access in mwifiex_get_power_level()

With "while (length)" check we may end up in accessing invalid
memory in last iteration.
This patch makes sure that tlv length is not less than the length
of structure mwifiex_power_group when min/max power is calculated.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Amitkumar Karwar 12 年之前
父节点
当前提交
fe1c9a443e
共有 1 个文件被更改,包括 12 次插入10 次删除
  1. 12 10
      drivers/net/wireless/mwifiex/sta_cmdresp.c

+ 12 - 10
drivers/net/wireless/mwifiex/sta_cmdresp.c

@@ -341,12 +341,16 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
 	pg = (struct mwifiex_power_group *)
 	pg = (struct mwifiex_power_group *)
 		((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
 		((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
 	length = le16_to_cpu(pg_tlv_hdr->length);
 	length = le16_to_cpu(pg_tlv_hdr->length);
-	if (length > 0) {
-		max_power = pg->power_max;
-		min_power = pg->power_min;
-		length -= sizeof(struct mwifiex_power_group);
-	}
-	while (length) {
+
+	/* At least one structure required to update power */
+	if (length < sizeof(struct mwifiex_power_group))
+		return 0;
+
+	max_power = pg->power_max;
+	min_power = pg->power_min;
+	length -= sizeof(struct mwifiex_power_group);
+
+	while (length >= sizeof(struct mwifiex_power_group)) {
 		pg++;
 		pg++;
 		if (max_power < pg->power_max)
 		if (max_power < pg->power_max)
 			max_power = pg->power_max;
 			max_power = pg->power_max;
@@ -356,10 +360,8 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
 
 
 		length -= sizeof(struct mwifiex_power_group);
 		length -= sizeof(struct mwifiex_power_group);
 	}
 	}
-	if (le16_to_cpu(pg_tlv_hdr->length) > 0) {
-		priv->min_tx_power_level = (u8) min_power;
-		priv->max_tx_power_level = (u8) max_power;
-	}
+	priv->min_tx_power_level = (u8) min_power;
+	priv->max_tx_power_level = (u8) max_power;
 
 
 	return 0;
 	return 0;
 }
 }