Преглед на файлове

qcacld-3.0: Possible OOB read when parsing FT IE

FTIE buffer carries multiple FT subelements (like R1KH-ID,
R0KH-ID, GTK, IGTK, etc).

Total FTIE buffer len = Number of FT subelements * (Subelement
ID (1 bytes) + lenght (1 bytes) + data length).

Currently, Host checks only the minimum length for FTIE buffer
while filling each FT subelements. This leads to OOB if the
remaining length of FTIE length buffer less than the length of
an FT subelement.

Before filling each subelement into FTIE buffer, add a check
to validate subelement length against remaining FTIE length

Change-Id: I5d6f4a59eef591d3a2da9f2403738d1fdd1a88b2
CRs-Fixed: 2857084
Abhinav Kumar преди 4 години
родител
ревизия
7404c2c964
променени са 1 файла, в които са добавени 13 реда и са изтрити 2 реда
  1. 13 2
      core/mac/src/sys/legacy/src/utils/src/parser_api.c

+ 13 - 2
core/mac/src/sys/legacy/src/utils/src/parser_api.c

@@ -3150,7 +3150,7 @@ QDF_STATUS wlan_parse_ftie_sha384(uint8_t *frame, uint32_t frame_len,
 				  struct sSirAssocRsp *assoc_rsp)
 {
 	const uint8_t *ie, *ie_end, *pos;
-	uint8_t ie_len;
+	uint8_t ie_len, remaining_ie_len;
 	struct wlan_sha384_ftinfo_subelem *ft_subelem;
 
 	ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_FTINFO, frame, frame_len);
@@ -3169,11 +3169,13 @@ QDF_STATUS wlan_parse_ftie_sha384(uint8_t *frame, uint32_t frame_len,
 		pe_err("Invalid FTIE len:%d", ie_len);
 		return QDF_STATUS_E_FAILURE;
 	}
+	remaining_ie_len = ie_len;
 	pos = ie + 2;
 	qdf_mem_copy(&assoc_rsp->sha384_ft_info, pos,
 		     sizeof(struct wlan_sha384_ftinfo));
 	ie_end = ie + ie_len;
 	pos += sizeof(struct wlan_sha384_ftinfo);
+	remaining_ie_len -= sizeof(struct wlan_sha384_ftinfo);
 	ft_subelem = &assoc_rsp->sha384_ft_subelem;
 	qdf_mem_zero(ft_subelem, sizeof(*ft_subelem));
 	while (ie_end - pos >= 2) {
@@ -3181,11 +3183,20 @@ QDF_STATUS wlan_parse_ftie_sha384(uint8_t *frame, uint32_t frame_len,
 
 		id = *pos++;
 		len = *pos++;
-		if (len < 1) {
+		/* Subtract data length(len) + 1 bytes for
+		 * Subelement ID + 1 bytes for length from
+		 * remaining FTIE buffer len (ie_len).
+		 * Subelement Parameter(s) field :
+		 *         Subelement ID  Length     Data
+		 * Octets:      1            1     variable
+		 */
+		if (len < 1 || remaining_ie_len < (len + 2)) {
 			pe_err("Invalid FT subelem length");
 			return QDF_STATUS_E_FAILURE;
 		}
 
+		remaining_ie_len -= (len + 2);
+
 		switch (id) {
 		case FTIE_SUBELEM_R1KH_ID:
 			if (len != FTIE_R1KH_LEN) {