Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 640e7cbc authored by Jyoti Kumari's avatar Jyoti Kumari
Browse files

qcacmn: Fix out of bound issue in util_scan_parse_mbssid()

During multiple BSSID scan ie parse, there is memory allocation
on new_ie variable of size 1024 which may create buffer overflow
in util_gen_new_ie() if ie length is greater than 1024.

As part of fix, allocate memory of size ie length in new_ie.
And also add check before copying to pos variable in
util_gen_new_ie().

Change-Id: I55e0819817b5a616684067170bf28a314a145fc2
CRs-Fixed: 2867353
parent 3195b9ac
Loading
Loading
Loading
Loading
+50 −23
Original line number Diff line number Diff line
@@ -1764,6 +1764,7 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
	uint8_t *pos, *tmp;
	const uint8_t *tmp_old, *tmp_new;
	uint8_t *sub_copy;
	size_t tmp_rem_len;

	/* copy subelement as we need to change its content to
	 * mark an ie after it is processed.
@@ -1779,9 +1780,11 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
	tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len);
	if (tmp_new) {
		scm_debug(" SSID %.*s", tmp_new[1], &tmp_new[2]);
		if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) {
			qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2);
			pos += (tmp_new[1] + 2);
		}
	}

	/* go through IEs in ie (skip SSID) and subelement,
	 * merge them into new_ie
@@ -1800,9 +1803,13 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
		if (!tmp) {
			/* ie in old ie but not in subelement */
			if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) {
				qdf_mem_copy(pos, tmp_old, tmp_old[1] + 2);
				if ((pos + tmp_old[1] + 2) <=
				    (new_ie + ielen)) {
					qdf_mem_copy(pos, tmp_old,
						     tmp_old[1] + 2);
					pos += tmp_old[1] + 2;
				}
			}
		} else {
			/* ie in transmitting ie also in subelement,
			 * copy from subelement and flag the ie in subelement
@@ -1810,37 +1817,55 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
			 * vendor ie, compare OUI + type + subType to
			 * determine if they are the same ie.
			 */
			if (tmp_old[0] == WLAN_ELEMID_VENDOR) {
			tmp_rem_len = subie_len - (tmp - sub_copy);
			if (tmp_old[0] == WLAN_ELEMID_VENDOR &&
			    tmp_rem_len >= 7) {
				if (!qdf_mem_cmp(tmp_old + 2, tmp + 2, 5)) {
					/* same vendor ie, copy from
					 * subelement
					 */
					qdf_mem_copy(pos, tmp, tmp[1] + 2);
					if ((pos + tmp[1] + 2) <=
					    (new_ie + ielen)) {
						qdf_mem_copy(pos, tmp,
							     tmp[1] + 2);
						pos += tmp[1] + 2;
						tmp[0] = 0;
					}
				} else {
					if ((pos + tmp_old[1] + 2) <=
					    (new_ie + ielen)) {
						qdf_mem_copy(pos, tmp_old,
							     tmp_old[1] + 2);
						pos += tmp_old[1] + 2;
					}
				}
			} else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM) {
				if (tmp_old[2] == tmp[2]) {
					/* same ie, copy from subelement */
					qdf_mem_copy(pos, tmp, tmp[1] + 2);
					if ((pos + tmp[1] + 2) <=
					    (new_ie + ielen)) {
						qdf_mem_copy(pos, tmp,
							     tmp[1] + 2);
						pos += tmp[1] + 2;
						tmp[0] = 0;
					}
				} else {
					if ((pos + tmp_old[1] + 2) <=
					    (new_ie + ielen)) {
						qdf_mem_copy(pos, tmp_old,
							     tmp_old[1] + 2);
						pos += tmp_old[1] + 2;
					}
				}
			} else {
				/* copy ie from subelement into new ie */
				if ((pos + tmp[1] + 2) <= (new_ie + ielen)) {
					qdf_mem_copy(pos, tmp, tmp[1] + 2);
					pos += tmp[1] + 2;
					tmp[0] = 0;
				}
			}
		}

		if (tmp_old + tmp_old[1] + 2 - ie == ielen)
			break;
@@ -1857,9 +1882,11 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
		      tmp_new[0] == WLAN_ELEMID_SSID ||
		      tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX ||
		      tmp_new[0] == 0xff)) {
			if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) {
				qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2);
				pos += tmp_new[1] + 2;
			}
		}
		if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len)
			break;
		tmp_new += tmp_new[1] + 2;
@@ -1900,7 +1927,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,

	pos = ie;

	new_ie = qdf_mem_malloc(MAX_IE_LEN);
	new_ie = qdf_mem_malloc(ielen);
	if (!new_ie)
		return QDF_STATUS_E_NOMEM;