aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-10-29 16:05:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-10-29 16:05:51 -0400
commitab3d59d265e772e734c36fe738809cb1a910f566 (patch)
treeb6d29908d3d45b078d025341b1cc272ba4c0a6d0 /net
parent42d36074e53eadfd79e6db518b5caf8fba914f8b (diff)
parent8c6e30936a7893a85f6222084f0f26aceb81137a (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts: drivers/net/wireless/mwifiex/cfg80211.c
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/mac80211/rx.c74
-rw-r--r--net/mac80211/util.c42
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/reg.c5
-rw-r--r--net/wireless/util.c14
6 files changed, 104 insertions, 36 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 3d5332e367f8..c7386b2b767e 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1110,7 +1110,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1110 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; 1110 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
1111 sdata->u.ibss.ibss_join_req = jiffies; 1111 sdata->u.ibss.ibss_join_req = jiffies;
1112 1112
1113 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); 1113 memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
1114 sdata->u.ibss.ssid_len = params->ssid_len; 1114 sdata->u.ibss.ssid_len = params->ssid_len;
1115 1115
1116 mutex_unlock(&sdata->u.ibss.mtx); 1116 mutex_unlock(&sdata->u.ibss.mtx);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d07216ab5f72..8c1f1527d671 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
531 531
532 if (ieee80211_is_action(hdr->frame_control)) { 532 if (ieee80211_is_action(hdr->frame_control)) {
533 u8 category; 533 u8 category;
534
535 /* make sure category field is present */
536 if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
537 return RX_DROP_MONITOR;
538
534 mgmt = (struct ieee80211_mgmt *)hdr; 539 mgmt = (struct ieee80211_mgmt *)hdr;
535 category = mgmt->u.action.category; 540 category = mgmt->u.action.category;
536 if (category != WLAN_CATEGORY_MESH_ACTION && 541 if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
883 */ 888 */
884 if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && 889 if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
885 ieee80211_is_data_present(hdr->frame_control)) { 890 ieee80211_is_data_present(hdr->frame_control)) {
886 u16 ethertype; 891 unsigned int hdrlen;
887 u8 *payload; 892 __be16 ethertype;
888 893
889 payload = rx->skb->data + 894 hdrlen = ieee80211_hdrlen(hdr->frame_control);
890 ieee80211_hdrlen(hdr->frame_control); 895
891 ethertype = (payload[6] << 8) | payload[7]; 896 if (rx->skb->len < hdrlen + 8)
892 if (cpu_to_be16(ethertype) == 897 return RX_DROP_MONITOR;
893 rx->sdata->control_port_protocol) 898
899 skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
900 if (ethertype == rx->sdata->control_port_protocol)
894 return RX_CONTINUE; 901 return RX_CONTINUE;
895 } 902 }
896 903
@@ -1467,11 +1474,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
1467 1474
1468 hdr = (struct ieee80211_hdr *)rx->skb->data; 1475 hdr = (struct ieee80211_hdr *)rx->skb->data;
1469 fc = hdr->frame_control; 1476 fc = hdr->frame_control;
1477
1478 if (ieee80211_is_ctl(fc))
1479 return RX_CONTINUE;
1480
1470 sc = le16_to_cpu(hdr->seq_ctrl); 1481 sc = le16_to_cpu(hdr->seq_ctrl);
1471 frag = sc & IEEE80211_SCTL_FRAG; 1482 frag = sc & IEEE80211_SCTL_FRAG;
1472 1483
1473 if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || 1484 if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
1474 (rx->skb)->len < 24 ||
1475 is_multicast_ether_addr(hdr->addr1))) { 1485 is_multicast_ether_addr(hdr->addr1))) {
1476 /* not fragmented */ 1486 /* not fragmented */
1477 goto out; 1487 goto out;
@@ -1894,6 +1904,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1894 1904
1895 hdr = (struct ieee80211_hdr *) skb->data; 1905 hdr = (struct ieee80211_hdr *) skb->data;
1896 hdrlen = ieee80211_hdrlen(hdr->frame_control); 1906 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1907
1908 /* make sure fixed part of mesh header is there, also checks skb len */
1909 if (!pskb_may_pull(rx->skb, hdrlen + 6))
1910 return RX_DROP_MONITOR;
1911
1912 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1913
1914 /* make sure full mesh header is there, also checks skb len */
1915 if (!pskb_may_pull(rx->skb,
1916 hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
1917 return RX_DROP_MONITOR;
1918
1919 /* reload pointers */
1920 hdr = (struct ieee80211_hdr *) skb->data;
1897 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); 1921 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1898 1922
1899 /* frame is in RMC, don't forward */ 1923 /* frame is in RMC, don't forward */
@@ -1902,7 +1926,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1902 mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) 1926 mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
1903 return RX_DROP_MONITOR; 1927 return RX_DROP_MONITOR;
1904 1928
1905 if (!ieee80211_is_data(hdr->frame_control)) 1929 if (!ieee80211_is_data(hdr->frame_control) ||
1930 !(status->rx_flags & IEEE80211_RX_RA_MATCH))
1906 return RX_CONTINUE; 1931 return RX_CONTINUE;
1907 1932
1908 if (!mesh_hdr->ttl) 1933 if (!mesh_hdr->ttl)
@@ -1916,9 +1941,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1916 if (is_multicast_ether_addr(hdr->addr1)) { 1941 if (is_multicast_ether_addr(hdr->addr1)) {
1917 mpp_addr = hdr->addr3; 1942 mpp_addr = hdr->addr3;
1918 proxied_addr = mesh_hdr->eaddr1; 1943 proxied_addr = mesh_hdr->eaddr1;
1919 } else { 1944 } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
1945 /* has_a4 already checked in ieee80211_rx_mesh_check */
1920 mpp_addr = hdr->addr4; 1946 mpp_addr = hdr->addr4;
1921 proxied_addr = mesh_hdr->eaddr2; 1947 proxied_addr = mesh_hdr->eaddr2;
1948 } else {
1949 return RX_DROP_MONITOR;
1922 } 1950 }
1923 1951
1924 rcu_read_lock(); 1952 rcu_read_lock();
@@ -1946,12 +1974,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1946 } 1974 }
1947 skb_set_queue_mapping(skb, q); 1975 skb_set_queue_mapping(skb, q);
1948 1976
1949 if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
1950 goto out;
1951
1952 if (!--mesh_hdr->ttl) { 1977 if (!--mesh_hdr->ttl) {
1953 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); 1978 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
1954 return RX_DROP_MONITOR; 1979 goto out;
1955 } 1980 }
1956 1981
1957 if (!ifmsh->mshcfg.dot11MeshForwarding) 1982 if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2358,6 +2383,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2358 } 2383 }
2359 break; 2384 break;
2360 case WLAN_CATEGORY_SELF_PROTECTED: 2385 case WLAN_CATEGORY_SELF_PROTECTED:
2386 if (len < (IEEE80211_MIN_ACTION_SIZE +
2387 sizeof(mgmt->u.action.u.self_prot.action_code)))
2388 break;
2389
2361 switch (mgmt->u.action.u.self_prot.action_code) { 2390 switch (mgmt->u.action.u.self_prot.action_code) {
2362 case WLAN_SP_MESH_PEERING_OPEN: 2391 case WLAN_SP_MESH_PEERING_OPEN:
2363 case WLAN_SP_MESH_PEERING_CLOSE: 2392 case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2376,6 +2405,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2376 } 2405 }
2377 break; 2406 break;
2378 case WLAN_CATEGORY_MESH_ACTION: 2407 case WLAN_CATEGORY_MESH_ACTION:
2408 if (len < (IEEE80211_MIN_ACTION_SIZE +
2409 sizeof(mgmt->u.action.u.mesh_action.action_code)))
2410 break;
2411
2379 if (!ieee80211_vif_is_mesh(&sdata->vif)) 2412 if (!ieee80211_vif_is_mesh(&sdata->vif))
2380 break; 2413 break;
2381 if (mesh_action_is_path_sel(mgmt) && 2414 if (mesh_action_is_path_sel(mgmt) &&
@@ -2918,10 +2951,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2918 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) 2951 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
2919 local->dot11ReceivedFragmentCount++; 2952 local->dot11ReceivedFragmentCount++;
2920 2953
2921 if (ieee80211_is_mgmt(fc)) 2954 if (ieee80211_is_mgmt(fc)) {
2922 err = skb_linearize(skb); 2955 /* drop frame if too short for header */
2923 else 2956 if (skb->len < ieee80211_hdrlen(fc))
2957 err = -ENOBUFS;
2958 else
2959 err = skb_linearize(skb);
2960 } else {
2924 err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); 2961 err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
2962 }
2925 2963
2926 if (err) { 2964 if (err) {
2927 dev_kfree_skb(skb); 2965 dev_kfree_skb(skb);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b3a84746d445..9556391b05d7 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
643 break; 643 break;
644 } 644 }
645 645
646 if (id != WLAN_EID_VENDOR_SPECIFIC && 646 switch (id) {
647 id != WLAN_EID_QUIET && 647 case WLAN_EID_SSID:
648 test_bit(id, seen_elems)) { 648 case WLAN_EID_SUPP_RATES:
649 elems->parse_error = true; 649 case WLAN_EID_FH_PARAMS:
650 left -= elen; 650 case WLAN_EID_DS_PARAMS:
651 pos += elen; 651 case WLAN_EID_CF_PARAMS:
652 continue; 652 case WLAN_EID_TIM:
653 case WLAN_EID_IBSS_PARAMS:
654 case WLAN_EID_CHALLENGE:
655 case WLAN_EID_RSN:
656 case WLAN_EID_ERP_INFO:
657 case WLAN_EID_EXT_SUPP_RATES:
658 case WLAN_EID_HT_CAPABILITY:
659 case WLAN_EID_HT_OPERATION:
660 case WLAN_EID_VHT_CAPABILITY:
661 case WLAN_EID_VHT_OPERATION:
662 case WLAN_EID_MESH_ID:
663 case WLAN_EID_MESH_CONFIG:
664 case WLAN_EID_PEER_MGMT:
665 case WLAN_EID_PREQ:
666 case WLAN_EID_PREP:
667 case WLAN_EID_PERR:
668 case WLAN_EID_RANN:
669 case WLAN_EID_CHANNEL_SWITCH:
670 case WLAN_EID_EXT_CHANSWITCH_ANN:
671 case WLAN_EID_COUNTRY:
672 case WLAN_EID_PWR_CONSTRAINT:
673 case WLAN_EID_TIMEOUT_INTERVAL:
674 if (test_bit(id, seen_elems)) {
675 elems->parse_error = true;
676 left -= elen;
677 pos += elen;
678 continue;
679 }
680 break;
653 } 681 }
654 682
655 if (calc_crc && id < 64 && (filter & (1ULL << id))) 683 if (calc_crc && id < 64 && (filter & (1ULL << id)))
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ce1ad776dfb5..26711f46a3be 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -529,8 +529,7 @@ int wiphy_register(struct wiphy *wiphy)
529 for (i = 0; i < sband->n_channels; i++) { 529 for (i = 0; i < sband->n_channels; i++) {
530 sband->channels[i].orig_flags = 530 sband->channels[i].orig_flags =
531 sband->channels[i].flags; 531 sband->channels[i].flags;
532 sband->channels[i].orig_mag = 532 sband->channels[i].orig_mag = INT_MAX;
533 sband->channels[i].max_antenna_gain;
534 sband->channels[i].orig_mpwr = 533 sband->channels[i].orig_mpwr =
535 sband->channels[i].max_power; 534 sband->channels[i].max_power;
536 sband->channels[i].band = band; 535 sband->channels[i].band = band;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 3b8cbbc214db..bcc7d7ee5a51 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,
908 map_regdom_flags(reg_rule->flags) | bw_flags; 908 map_regdom_flags(reg_rule->flags) | bw_flags;
909 chan->max_antenna_gain = chan->orig_mag = 909 chan->max_antenna_gain = chan->orig_mag =
910 (int) MBI_TO_DBI(power_rule->max_antenna_gain); 910 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
911 chan->max_power = chan->orig_mpwr = 911 chan->max_reg_power = chan->max_power = chan->orig_mpwr =
912 (int) MBM_TO_DBM(power_rule->max_eirp); 912 (int) MBM_TO_DBM(power_rule->max_eirp);
913 return; 913 return;
914 } 914 }
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
1331 1331
1332 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; 1332 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1333 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1333 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1334 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1334 chan->max_reg_power = chan->max_power =
1335 (int) MBM_TO_DBM(power_rule->max_eirp);
1335} 1336}
1336 1337
1337static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, 1338static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 343f13c1d31d..5b6c1df72f31 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -311,23 +311,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
311} 311}
312EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); 312EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
313 313
314static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) 314unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
315{ 315{
316 int ae = meshhdr->flags & MESH_FLAGS_AE; 316 int ae = meshhdr->flags & MESH_FLAGS_AE;
317 /* 7.1.3.5a.2 */ 317 /* 802.11-2012, 8.2.4.7.3 */
318 switch (ae) { 318 switch (ae) {
319 default:
319 case 0: 320 case 0:
320 return 6; 321 return 6;
321 case MESH_FLAGS_AE_A4: 322 case MESH_FLAGS_AE_A4:
322 return 12; 323 return 12;
323 case MESH_FLAGS_AE_A5_A6: 324 case MESH_FLAGS_AE_A5_A6:
324 return 18; 325 return 18;
325 case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
326 return 24;
327 default:
328 return 6;
329 } 326 }
330} 327}
328EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
331 329
332int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, 330int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
333 enum nl80211_iftype iftype) 331 enum nl80211_iftype iftype)
@@ -375,6 +373,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
375 /* make sure meshdr->flags is on the linear part */ 373 /* make sure meshdr->flags is on the linear part */
376 if (!pskb_may_pull(skb, hdrlen + 1)) 374 if (!pskb_may_pull(skb, hdrlen + 1))
377 return -1; 375 return -1;
376 if (meshdr->flags & MESH_FLAGS_AE_A4)
377 return -1;
378 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { 378 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
379 skb_copy_bits(skb, hdrlen + 379 skb_copy_bits(skb, hdrlen +
380 offsetof(struct ieee80211s_hdr, eaddr1), 380 offsetof(struct ieee80211s_hdr, eaddr1),
@@ -399,6 +399,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
399 /* make sure meshdr->flags is on the linear part */ 399 /* make sure meshdr->flags is on the linear part */
400 if (!pskb_may_pull(skb, hdrlen + 1)) 400 if (!pskb_may_pull(skb, hdrlen + 1))
401 return -1; 401 return -1;
402 if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
403 return -1;
402 if (meshdr->flags & MESH_FLAGS_AE_A4) 404 if (meshdr->flags & MESH_FLAGS_AE_A4)
403 skb_copy_bits(skb, hdrlen + 405 skb_copy_bits(skb, hdrlen +
404 offsetof(struct ieee80211s_hdr, eaddr1), 406 offsetof(struct ieee80211s_hdr, eaddr1),