浏览代码

qcacmn: Fix out-of-bound in wlan_mlo_parse_bcn_prbresp_t2lm_ie

Currently, In the MLO t2lm API, wlan_mlo_parse_bcn_prbresp_t2lm_ie
is missing frame boundary checks which may lead to out-of-bound
reads if the lengths are not checked by the caller.

Fix is, while parsing t2lm ie pass the frame length and add
check for frame boundary.

CRs-Fixed: 3704739
Change-Id: If3068db3489ee1c9a9da4945407598e27e3ca276
Krupali Dhanvijay 1 年之前
父节点
当前提交
f323c32b7d

+ 6 - 3
umac/mlo_mgr/inc/wlan_mlo_t2lm.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -627,11 +627,13 @@ uint8_t *wlan_mlo_add_t2lm_action_frame(
  * probe response frame
  * @t2lm_ctx: T2LM context
  * @ie: Pointer to T2LM IE
+ * @frame_len: Frame length
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie(
-		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie);
+		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie,
+		uint32_t frame_len);
 
 /**
  * wlan_mlo_parse_t2lm_info() - Parse T2LM IE fields
@@ -804,7 +806,8 @@ uint8_t *wlan_mlo_add_t2lm_action_frame(
 
 static inline
 QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie(
-		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie)
+		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie,
+		uint32_t frame_len)
 {
 	return QDF_STATUS_E_FAILURE;
 }

+ 21 - 4
umac/mlo_mgr/src/wlan_mlo_t2lm.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -140,12 +140,14 @@ QDF_STATUS wlan_mlo_parse_t2lm_info(uint8_t *ie,
 }
 
 QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie(
-		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie)
+		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie,
+		uint32_t frame_len)
 {
 	struct wlan_t2lm_info t2lm = {0};
 	struct extn_ie_header *ext_ie_hdr;
 	QDF_STATUS retval;
 	int i = 0;
+	uint32_t ie_len_parsed = 0;
 
 	qdf_mem_zero(&t2lm_ctx->established_t2lm,
 		     sizeof(struct wlan_mlo_t2lm_ie));
@@ -155,17 +157,32 @@ QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie(
 	t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
 
 	for (i = 0; i < WLAN_MAX_T2LM_IE; i++) {
-		if (!ie) {
-			t2lm_err("ie is null");
+		if (!ie || !frame_len) {
+			t2lm_debug("ie is null or len is 0");
 			return QDF_STATUS_E_NULL_VALUE;
 		}
 
+		if (frame_len == ie_len_parsed)
+			return QDF_STATUS_SUCCESS;
+
+		if (frame_len < (ie_len_parsed +
+				 sizeof(struct extn_ie_header))) {
+			t2lm_debug("Frame length is lesser than parsed T2LM IE header length");
+			continue;
+		}
+
 		ext_ie_hdr = (struct extn_ie_header *)ie;
 
 		if (!(ext_ie_hdr->ie_id == WLAN_ELEMID_EXTN_ELEM &&
 		      ext_ie_hdr->ie_extn_id == WLAN_EXTN_ELEMID_T2LM))
 			continue;
 
+		ie_len_parsed += ext_ie_hdr->ie_len + sizeof(struct ie_header);
+		if (frame_len < ie_len_parsed) {
+			t2lm_debug("Frame length is lesser than parsed T2LM IE length");
+			continue;
+		}
+
 		t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
 		retval = wlan_mlo_parse_t2lm_info(ie, &t2lm);
 		if (retval) {

+ 14 - 0
umac/scan/dispatcher/inc/wlan_scan_utils_api.h

@@ -1647,12 +1647,26 @@ util_scan_entry_t2lm(struct scan_cache_entry *scan_entry)
 {
 	return scan_entry->ie_list.t2lm[0];
 }
+
+/**
+ * util_scan_entry_t2lm_len() - API to get t2lm IE length
+ * @scan_entry: scan entry
+ *
+ * Return, Length or 0 if ie is not present
+ */
+uint32_t util_scan_entry_t2lm_len(struct scan_cache_entry *scan_entry);
 #else
 static inline uint8_t*
 util_scan_entry_t2lm(struct scan_cache_entry *scan_entry)
 {
 	return NULL;
 }
+
+static inline uint32_t
+util_scan_entry_t2lm_len(struct scan_cache_entry *scan_entry)
+{
+	return 0;
+}
 #endif
 
 /**

+ 19 - 0
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -126,6 +126,25 @@ util_get_last_scan_time(struct wlan_objmgr_vdev *vdev)
 		return 0;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+uint32_t util_scan_entry_t2lm_len(struct scan_cache_entry *scan_entry)
+{
+	int i = 0;
+	uint32_t len = 0;
+
+	if (!scan_entry || !scan_entry->ie_list.t2lm[0])
+		return 0;
+
+	for (i = 0; i < WLAN_MAX_T2LM_IE; i++) {
+		if (scan_entry->ie_list.t2lm[i])
+			len += scan_entry->ie_list.t2lm[i][TAG_LEN_POS] +
+				sizeof(struct ie_header);
+	}
+
+	return len;
+}
+#endif
+
 bool util_is_rsnxe_h2e_capable(const uint8_t *rsnxe)
 {
 	const uint8_t *rsnxe_caps;