summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-05-31 09:18:41 -0400
committerKalle Valo <kvalo@codeaurora.org>2019-06-01 01:06:24 -0400
commit69ae4f6aac1578575126319d3f55550e7e440449 (patch)
treeeb6c70372232d2632785ecc467ddd5718b6cb109 /drivers/net/wireless
parent5f4d55d5791a8b7150dbaba239e92719ae0f94d4 (diff)
mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies()
A few places in mwifiex_uap_parse_tail_ies() perform memcpy() unconditionally, which may lead to either buffer overflow or read over boundary. This patch addresses the issues by checking the read size and the destination size at each place more properly. Along with the fixes, the patch cleans up the code slightly by introducing a temporary variable for the token size, and unifies the error path with the standard goto statement. Reported-by: huangwen <huangwen@venustech.com.cn> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/marvell/mwifiex/ie.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c
index 6845eb57b39a..653d347a9a19 100644
--- a/drivers/net/wireless/marvell/mwifiex/ie.c
+++ b/drivers/net/wireless/marvell/mwifiex/ie.c
@@ -329,6 +329,8 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
329 struct ieee80211_vendor_ie *vendorhdr; 329 struct ieee80211_vendor_ie *vendorhdr;
330 u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; 330 u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
331 int left_len, parsed_len = 0; 331 int left_len, parsed_len = 0;
332 unsigned int token_len;
333 int err = 0;
332 334
333 if (!info->tail || !info->tail_len) 335 if (!info->tail || !info->tail_len)
334 return 0; 336 return 0;
@@ -344,6 +346,12 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
344 */ 346 */
345 while (left_len > sizeof(struct ieee_types_header)) { 347 while (left_len > sizeof(struct ieee_types_header)) {
346 hdr = (void *)(info->tail + parsed_len); 348 hdr = (void *)(info->tail + parsed_len);
349 token_len = hdr->len + sizeof(struct ieee_types_header);
350 if (token_len > left_len) {
351 err = -EINVAL;
352 goto out;
353 }
354
347 switch (hdr->element_id) { 355 switch (hdr->element_id) {
348 case WLAN_EID_SSID: 356 case WLAN_EID_SSID:
349 case WLAN_EID_SUPP_RATES: 357 case WLAN_EID_SUPP_RATES:
@@ -361,17 +369,20 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
361 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, 369 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
362 WLAN_OUI_TYPE_MICROSOFT_WMM, 370 WLAN_OUI_TYPE_MICROSOFT_WMM,
363 (const u8 *)hdr, 371 (const u8 *)hdr,
364 hdr->len + sizeof(struct ieee_types_header))) 372 token_len))
365 break; 373 break;
366 /* fall through */ 374 /* fall through */
367 default: 375 default:
368 memcpy(gen_ie->ie_buffer + ie_len, hdr, 376 if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
369 hdr->len + sizeof(struct ieee_types_header)); 377 err = -EINVAL;
370 ie_len += hdr->len + sizeof(struct ieee_types_header); 378 goto out;
379 }
380 memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
381 ie_len += token_len;
371 break; 382 break;
372 } 383 }
373 left_len -= hdr->len + sizeof(struct ieee_types_header); 384 left_len -= token_len;
374 parsed_len += hdr->len + sizeof(struct ieee_types_header); 385 parsed_len += token_len;
375 } 386 }
376 387
377 /* parse only WPA vendor IE from tail, WMM IE is configured by 388 /* parse only WPA vendor IE from tail, WMM IE is configured by
@@ -381,15 +392,17 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
381 WLAN_OUI_TYPE_MICROSOFT_WPA, 392 WLAN_OUI_TYPE_MICROSOFT_WPA,
382 info->tail, info->tail_len); 393 info->tail, info->tail_len);
383 if (vendorhdr) { 394 if (vendorhdr) {
384 memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, 395 token_len = vendorhdr->len + sizeof(struct ieee_types_header);
385 vendorhdr->len + sizeof(struct ieee_types_header)); 396 if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
386 ie_len += vendorhdr->len + sizeof(struct ieee_types_header); 397 err = -EINVAL;
398 goto out;
399 }
400 memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
401 ie_len += token_len;
387 } 402 }
388 403
389 if (!ie_len) { 404 if (!ie_len)
390 kfree(gen_ie); 405 goto out;
391 return 0;
392 }
393 406
394 gen_ie->ie_index = cpu_to_le16(gen_idx); 407 gen_ie->ie_index = cpu_to_le16(gen_idx);
395 gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | 408 gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
@@ -399,13 +412,15 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
399 412
400 if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL, 413 if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
401 NULL, NULL)) { 414 NULL, NULL)) {
402 kfree(gen_ie); 415 err = -EINVAL;
403 return -1; 416 goto out;
404 } 417 }
405 418
406 priv->gen_idx = gen_idx; 419 priv->gen_idx = gen_idx;
420
421 out:
407 kfree(gen_ie); 422 kfree(gen_ie);
408 return 0; 423 return err;
409} 424}
410 425
411/* This function parses different IEs-head & tail IEs, beacon IEs, 426/* This function parses different IEs-head & tail IEs, beacon IEs,