[PATCH wireless-next 4/4] wifi: mm81x: bound the extended host table walk

Linmao Li <[email protected]>
Newsgroups org.kernel.vger.linux-wireless,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The extended host table is read from the chip into a buffer sized from
the length register, then walked without any of its contents being
checked:

 - the length the table declares in its own header is used to compute
   the end pointer, but is never compared against the length that was
   read, so a larger value moves the end pointer past the buffer;
 - the walk only requires a TLV header to start before that end, so a
   header straddling it is read anyway;
 - every recognised tag is cast to a structure larger than the TLV
   header and read in full without checking that the TLV is that long,
   so a short S1G capabilities, checksum or YAPS TLV at the end of the
   table reads past the allocation.

Firmware that reports a table the driver does not agree with is enough
to reach these; it does not take a malicious device.

Reject a self-declared length that does not fit what was read, and walk
the TLVs by remaining length, skipping any TLV too short for the
structure its tag selects.

Fixes: b1906cea00b0 ("wifi: mm81x: add mm81x Wi-Fi HaLow driver")
Signed-off-by: Linmao Li <[email protected]>
---
 drivers/net/wireless/morsemicro/mm81x/fw.c | 47 +++++++++++++++-------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/morsemicro/mm81x/fw.c b/drivers/net/wireless/morsemicro/mm81x/fw.c
index d2fba42e53627..50fa9e4b5f803 100644
--- a/drivers/net/wireless/morsemicro/mm81x/fw.c
+++ b/drivers/net/wireless/morsemicro/mm81x/fw.c
@@ -503,6 +503,13 @@ static int mm81x_fw_read_ext_host_table(struct mm81x *mors,
 	if (ret)
 		goto exit;
 
+	/* The table describes its own length; it must fit what was read */
+	if (le32_to_cpu(host_tbl->ext_host_tbl_length) < sizeof(*host_tbl) ||
+	    le32_to_cpu(host_tbl->ext_host_tbl_length) > ext_host_tbl_len) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	mm81x_release_bus(mors);
 	*ext_host_table = host_tbl;
 	return ret;
@@ -570,34 +577,44 @@ int mm81x_fw_parse_ext_host_tbl(struct mm81x *mors)
 	end = ((u8 *)ext_host_table) +
 	      le32_to_cpu(ext_host_table->ext_host_tbl_length);
 
-	while (head < end) {
+	while (end - head >= (ptrdiff_t)sizeof(struct ext_host_tbl_tlv_hdr)) {
 		struct ext_host_tbl_tlv_hdr *hdr =
 			(struct ext_host_tbl_tlv_hdr *)head;
+		u16 tlv_len = le16_to_cpu(hdr->length);
+
+		if (tlv_len < sizeof(*hdr) || tlv_len > end - head)
+			break;
 
 		switch (le16_to_cpu(hdr->tag)) {
-		case MM81X_FW_HOST_TABLE_TAG_S1G_CAPABILITIES:
-			mm81x_fw_update_capabilities(
-				mors, (struct ext_host_tbl_s1g_caps *)hdr);
+		case MM81X_FW_HOST_TABLE_TAG_S1G_CAPABILITIES: {
+			struct ext_host_tbl_s1g_caps *caps = (void *)hdr;
+
+			if (tlv_len >= sizeof(*caps))
+				mm81x_fw_update_capabilities(mors, caps);
 			break;
+		}
+		case MM81X_FW_HOST_TABLE_TAG_INSERT_SKB_CHECKSUM: {
+			struct ext_host_tbl_insert_skb_checksum *csum =
+				(void *)hdr;
 
-		case MM81X_FW_HOST_TABLE_TAG_INSERT_SKB_CHECKSUM:
-			mm81x_fw_update_validate_skb_checksum(
-				mors,
-				(struct ext_host_tbl_insert_skb_checksum *)hdr);
+			if (tlv_len >= sizeof(*csum))
+				mm81x_fw_update_validate_skb_checksum(mors,
+								      csum);
 			break;
+		}
+		case MM81X_FW_HOST_TABLE_TAG_YAPS_TABLE: {
+			struct ext_host_tbl_yaps_table *yaps = (void *)hdr;
 
-		case MM81X_FW_HOST_TABLE_TAG_YAPS_TABLE:
-			mm81x_yaps_hw_read_table(
-				mors, &((struct ext_host_tbl_yaps_table *)hdr)
-					       ->yaps_table);
+			if (tlv_len >= sizeof(*yaps))
+				mm81x_yaps_hw_read_table(mors,
+							 &yaps->yaps_table);
 			break;
+		}
 		default:
 			break;
 		}
 
-		head += le16_to_cpu(hdr->length);
-		if (!hdr->length)
-			break;
+		head += tlv_len;
 	}
 
 	kfree(ext_host_table);
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.