浏览代码

qcacmn: Fix memory leak if beacon is corrupted

In case of split profile, while parsing the other segment
of the non transmitted profile present in the subsequent
MBSSID tag, it is possible that the beacon is corrupted where
the non tx profile length has gone out of bound.
In case of above scenario, the MBSSIE parsing code does not
free up the memory allocated for split_prof_start before
returning, which could possibly result into a memmory leak.

Handling the split_profile_continue bit before non tx profile
length check can avoid this situation.

Change-Id: Iaa491fd2803d88759e74ca5a668dddb9f8a42708
CRs-Fixed: 3023554
Adwait Nayak 3 年之前
父节点
当前提交
535fd627c8
共有 1 个文件被更改,包括 28 次插入12 次删除
  1. 28 12
      umac/scan/dispatcher/src/wlan_scan_utils_api.c

+ 28 - 12
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -2467,18 +2467,6 @@ util_handle_nontx_prof(uint8_t *mbssid_elem, uint8_t *subelement,
 	uint32_t prof_len;
 
 	prof_len = subelement[TAG_LEN_POS];
-	/*
-	 * if prof_residue is true, that means we are
-	 * in the continuation of the fragmented profile part,
-	 * present in the next MBSSD IE else this profile
-	 * is a non fragmented non tx BSSID profile.
-	 */
-
-	if (mbssid_info->prof_residue)
-		mbssid_info->split_prof_continue = true;
-	else
-		mbssid_info->split_prof_continue = false;
-
 	/*
 	 * If we are executing the split portion of the nontx
 	 * profile present in the subsequent MBSSID, then there
@@ -2662,7 +2650,25 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
 		     subelement += MIN_IE_LEN + subelement[TAG_LEN_POS]) {
 			subie_len = subelement[TAG_LEN_POS];
 
+			/*
+			 * if prof_residue is true, that means we are
+			 * in the continuation of the fragmented profile part,
+			 * present in the next MBSSD IE else this profile
+			 * is a non fragmented non tx BSSID profile.
+			 */
+
+			if (mbssid_info.prof_residue)
+				mbssid_info.split_prof_continue = true;
+			else
+				mbssid_info.split_prof_continue = false;
+
 			if (subie_len > MAX_SUBELEM_LEN) {
+				scm_err_rl("Corrupt frame with subie_len: %d\n"
+					   "split_prof_continue: %d\n"
+					   "prof_residue: %d\n",
+					   subie_len,
+					   mbssid_info.split_prof_continue,
+					   mbssid_info.prof_residue);
 				if (mbssid_info.split_prof_continue)
 					qdf_mem_free(split_prof_start);
 
@@ -2681,6 +2687,10 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
 							bssid, new_bssid);
 
 			if (retval == INVALID_SPLIT_PROF) {
+				scm_err_rl("Corrupt frame with ID_POS: %d\n"
+					   "TAG_LEN_POS: %d\n",
+					   subelement[ID_POS],
+					   subelement[TAG_LEN_POS]);
 				qdf_mem_free(split_prof_start);
 				qdf_mem_free(new_ie);
 				return QDF_STATUS_E_INVAL;
@@ -2715,6 +2725,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
 					split_prof_start =
 						qdf_mem_malloc(ielen);
 					if (!split_prof_start) {
+						scm_err_rl("Malloc failed");
 						qdf_mem_free(new_ie);
 						return QDF_STATUS_E_NOMEM;
 					}
@@ -2812,6 +2823,9 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
 				if (mbssid_info.split_prof_continue)
 					qdf_mem_free(split_prof_start);
 				qdf_mem_free(new_ie);
+				scm_err_rl("Malloc for new_frame failed");
+				scm_err_rl("split_prof_continue: %d",
+					   mbssid_info.split_prof_continue);
 				return QDF_STATUS_E_NOMEM;
 			}
 
@@ -2852,6 +2866,8 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
 				}
 				qdf_mem_free(new_frame);
 				scm_err_rl("failed to generate a scan entry");
+				scm_err_rl("split_prof_continue: %d",
+					   mbssid_info.split_prof_continue);
 				break;
 			}
 			/* scan entry makes its own copy so free the frame*/