diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/ie.c | 47 |
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, |