aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0a5ad95ac8b0..32f7a3b3d43c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -572,24 +572,40 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
572 size_t left = len; 572 size_t left = len;
573 u8 *pos = start; 573 u8 *pos = start;
574 bool calc_crc = filter != 0; 574 bool calc_crc = filter != 0;
575 DECLARE_BITMAP(seen_elems, 256);
575 576
577 bitmap_zero(seen_elems, 256);
576 memset(elems, 0, sizeof(*elems)); 578 memset(elems, 0, sizeof(*elems));
577 elems->ie_start = start; 579 elems->ie_start = start;
578 elems->total_len = len; 580 elems->total_len = len;
579 581
580 while (left >= 2) { 582 while (left >= 2) {
581 u8 id, elen; 583 u8 id, elen;
584 bool elem_parse_failed;
582 585
583 id = *pos++; 586 id = *pos++;
584 elen = *pos++; 587 elen = *pos++;
585 left -= 2; 588 left -= 2;
586 589
587 if (elen > left) 590 if (elen > left) {
591 elems->parse_error = true;
588 break; 592 break;
593 }
594
595 if (id != WLAN_EID_VENDOR_SPECIFIC &&
596 id != WLAN_EID_QUIET &&
597 test_bit(id, seen_elems)) {
598 elems->parse_error = true;
599 left -= elen;
600 pos += elen;
601 continue;
602 }
589 603
590 if (calc_crc && id < 64 && (filter & (1ULL << id))) 604 if (calc_crc && id < 64 && (filter & (1ULL << id)))
591 crc = crc32_be(crc, pos - 2, elen + 2); 605 crc = crc32_be(crc, pos - 2, elen + 2);
592 606
607 elem_parse_failed = false;
608
593 switch (id) { 609 switch (id) {
594 case WLAN_EID_SSID: 610 case WLAN_EID_SSID:
595 elems->ssid = pos; 611 elems->ssid = pos;
@@ -615,7 +631,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
615 if (elen >= sizeof(struct ieee80211_tim_ie)) { 631 if (elen >= sizeof(struct ieee80211_tim_ie)) {
616 elems->tim = (void *)pos; 632 elems->tim = (void *)pos;
617 elems->tim_len = elen; 633 elems->tim_len = elen;
618 } 634 } else
635 elem_parse_failed = true;
619 break; 636 break;
620 case WLAN_EID_IBSS_PARAMS: 637 case WLAN_EID_IBSS_PARAMS:
621 elems->ibss_params = pos; 638 elems->ibss_params = pos;
@@ -664,10 +681,14 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
664 case WLAN_EID_HT_CAPABILITY: 681 case WLAN_EID_HT_CAPABILITY:
665 if (elen >= sizeof(struct ieee80211_ht_cap)) 682 if (elen >= sizeof(struct ieee80211_ht_cap))
666 elems->ht_cap_elem = (void *)pos; 683 elems->ht_cap_elem = (void *)pos;
684 else
685 elem_parse_failed = true;
667 break; 686 break;
668 case WLAN_EID_HT_INFORMATION: 687 case WLAN_EID_HT_INFORMATION:
669 if (elen >= sizeof(struct ieee80211_ht_info)) 688 if (elen >= sizeof(struct ieee80211_ht_info))
670 elems->ht_info_elem = (void *)pos; 689 elems->ht_info_elem = (void *)pos;
690 else
691 elem_parse_failed = true;
671 break; 692 break;
672 case WLAN_EID_MESH_ID: 693 case WLAN_EID_MESH_ID:
673 elems->mesh_id = pos; 694 elems->mesh_id = pos;
@@ -676,6 +697,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
676 case WLAN_EID_MESH_CONFIG: 697 case WLAN_EID_MESH_CONFIG:
677 if (elen >= sizeof(struct ieee80211_meshconf_ie)) 698 if (elen >= sizeof(struct ieee80211_meshconf_ie))
678 elems->mesh_config = (void *)pos; 699 elems->mesh_config = (void *)pos;
700 else
701 elem_parse_failed = true;
679 break; 702 break;
680 case WLAN_EID_PEER_MGMT: 703 case WLAN_EID_PEER_MGMT:
681 elems->peering = pos; 704 elems->peering = pos;
@@ -696,6 +719,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
696 case WLAN_EID_RANN: 719 case WLAN_EID_RANN:
697 if (elen >= sizeof(struct ieee80211_rann_ie)) 720 if (elen >= sizeof(struct ieee80211_rann_ie))
698 elems->rann = (void *)pos; 721 elems->rann = (void *)pos;
722 else
723 elem_parse_failed = true;
699 break; 724 break;
700 case WLAN_EID_CHANNEL_SWITCH: 725 case WLAN_EID_CHANNEL_SWITCH:
701 elems->ch_switch_elem = pos; 726 elems->ch_switch_elem = pos;
@@ -724,10 +749,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
724 break; 749 break;
725 } 750 }
726 751
752 if (elem_parse_failed)
753 elems->parse_error = true;
754 else
755 set_bit(id, seen_elems);
756
727 left -= elen; 757 left -= elen;
728 pos += elen; 758 pos += elen;
729 } 759 }
730 760
761 if (left != 0)
762 elems->parse_error = true;
763
731 return crc; 764 return crc;
732} 765}
733 766