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
Este commit está contenido en:
@@ -1800,6 +1800,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.
|
||||
@@ -1815,12 +1816,10 @@ 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 - new_ie + tmp_new[1] + 2) > MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2);
|
||||
pos += (tmp_new[1] + 2);
|
||||
}
|
||||
qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2);
|
||||
pos += (tmp_new[1] + 2);
|
||||
}
|
||||
|
||||
/* go through IEs in ie (skip SSID) and subelement,
|
||||
@@ -1840,13 +1839,12 @@ 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) {
|
||||
if ((pos - new_ie + tmp_old[1] + 2) >
|
||||
MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp_old[1] + 2) <=
|
||||
(new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp_old,
|
||||
tmp_old[1] + 2);
|
||||
pos += tmp_old[1] + 2;
|
||||
}
|
||||
qdf_mem_copy(pos, tmp_old, tmp_old[1] + 2);
|
||||
pos += tmp_old[1] + 2;
|
||||
}
|
||||
} else {
|
||||
/* ie in transmitting ie also in subelement,
|
||||
@@ -1855,59 +1853,53 @@ 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
|
||||
*/
|
||||
if ((pos - new_ie + tmp[1] + 2) >
|
||||
MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp[1] + 2) <=
|
||||
(new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp,
|
||||
tmp[1] + 2);
|
||||
pos += tmp[1] + 2;
|
||||
tmp[0] = 0;
|
||||
}
|
||||
qdf_mem_copy(pos, tmp, tmp[1] + 2);
|
||||
pos += tmp[1] + 2;
|
||||
tmp[0] = 0;
|
||||
} else {
|
||||
if ((pos - new_ie + tmp_old[1] + 2) >
|
||||
MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp_old[1] + 2) <=
|
||||
(new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp_old,
|
||||
tmp_old[1] + 2);
|
||||
pos += tmp_old[1] + 2;
|
||||
}
|
||||
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 */
|
||||
if ((pos - new_ie + tmp[1] + 2) >
|
||||
MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp[1] + 2) <=
|
||||
(new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp,
|
||||
tmp[1] + 2);
|
||||
pos += tmp[1] + 2;
|
||||
tmp[0] = 0;
|
||||
}
|
||||
qdf_mem_copy(pos, tmp, tmp[1] + 2);
|
||||
pos += tmp[1] + 2;
|
||||
tmp[0] = 0;
|
||||
} else {
|
||||
if ((pos - new_ie + tmp_old[1] + 2) >
|
||||
MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp_old[1] + 2) <=
|
||||
(new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp_old,
|
||||
tmp_old[1] + 2);
|
||||
pos += tmp_old[1] + 2;
|
||||
}
|
||||
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 - new_ie + tmp[1] + 2) > MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp[1] + 2) <= (new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp, tmp[1] + 2);
|
||||
pos += tmp[1] + 2;
|
||||
tmp[0] = 0;
|
||||
}
|
||||
qdf_mem_copy(pos, tmp, tmp[1] + 2);
|
||||
pos += tmp[1] + 2;
|
||||
tmp[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1925,12 +1917,10 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
|
||||
if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP ||
|
||||
tmp_new[0] == WLAN_ELEMID_SSID ||
|
||||
tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX)) {
|
||||
if ((pos - new_ie + tmp_new[1] + 2) > MAX_IE_LEN) {
|
||||
qdf_mem_free(sub_copy);
|
||||
return 0;
|
||||
if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) {
|
||||
qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2);
|
||||
pos += tmp_new[1] + 2;
|
||||
}
|
||||
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;
|
||||
@@ -1976,7 +1966,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;
|
||||
|
||||
|
Referencia en una nueva incidencia
Block a user