aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c74
1 files changed, 56 insertions, 18 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 61c621e9273f..00ade7feb2e3 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
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
1462 1469
1463 hdr = (struct ieee80211_hdr *)rx->skb->data; 1470 hdr = (struct ieee80211_hdr *)rx->skb->data;
1464 fc = hdr->frame_control; 1471 fc = hdr->frame_control;
1472
1473 if (ieee80211_is_ctl(fc))
1474 return RX_CONTINUE;
1475
1465 sc = le16_to_cpu(hdr->seq_ctrl); 1476 sc = le16_to_cpu(hdr->seq_ctrl);
1466 frag = sc & IEEE80211_SCTL_FRAG; 1477 frag = sc & IEEE80211_SCTL_FRAG;
1467 1478
1468 if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || 1479 if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
1469 (rx->skb)->len < 24 ||
1470 is_multicast_ether_addr(hdr->addr1))) { 1480 is_multicast_ether_addr(hdr->addr1))) {
1471 /* not fragmented */ 1481 /* not fragmented */
1472 goto out; 1482 goto out;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1889 1899
1890 hdr = (struct ieee80211_hdr *) skb->data; 1900 hdr = (struct ieee80211_hdr *) skb->data;
1891 hdrlen = ieee80211_hdrlen(hdr->frame_control); 1901 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1902
1903 /* make sure fixed part of mesh header is there, also checks skb len */
1904 if (!pskb_may_pull(rx->skb, hdrlen + 6))
1905 return RX_DROP_MONITOR;
1906
1907 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1908
1909 /* make sure full mesh header is there, also checks skb len */
1910 if (!pskb_may_pull(rx->skb,
1911 hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
1912 return RX_DROP_MONITOR;
1913
1914 /* reload pointers */
1915 hdr = (struct ieee80211_hdr *) skb->data;
1892 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); 1916 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1893 1917
1894 /* frame is in RMC, don't forward */ 1918 /* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1897 mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) 1921 mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
1898 return RX_DROP_MONITOR; 1922 return RX_DROP_MONITOR;
1899 1923
1900 if (!ieee80211_is_data(hdr->frame_control)) 1924 if (!ieee80211_is_data(hdr->frame_control) ||
1925 !(status->rx_flags & IEEE80211_RX_RA_MATCH))
1901 return RX_CONTINUE; 1926 return RX_CONTINUE;
1902 1927
1903 if (!mesh_hdr->ttl) 1928 if (!mesh_hdr->ttl)
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1911 if (is_multicast_ether_addr(hdr->addr1)) { 1936 if (is_multicast_ether_addr(hdr->addr1)) {
1912 mpp_addr = hdr->addr3; 1937 mpp_addr = hdr->addr3;
1913 proxied_addr = mesh_hdr->eaddr1; 1938 proxied_addr = mesh_hdr->eaddr1;
1914 } else { 1939 } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
1940 /* has_a4 already checked in ieee80211_rx_mesh_check */
1915 mpp_addr = hdr->addr4; 1941 mpp_addr = hdr->addr4;
1916 proxied_addr = mesh_hdr->eaddr2; 1942 proxied_addr = mesh_hdr->eaddr2;
1943 } else {
1944 return RX_DROP_MONITOR;
1917 } 1945 }
1918 1946
1919 rcu_read_lock(); 1947 rcu_read_lock();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1941 } 1969 }
1942 skb_set_queue_mapping(skb, q); 1970 skb_set_queue_mapping(skb, q);
1943 1971
1944 if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
1945 goto out;
1946
1947 if (!--mesh_hdr->ttl) { 1972 if (!--mesh_hdr->ttl) {
1948 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); 1973 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
1949 return RX_DROP_MONITOR; 1974 goto out;
1950 } 1975 }
1951 1976
1952 if (!ifmsh->mshcfg.dot11MeshForwarding) 1977 if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2353 } 2378 }
2354 break; 2379 break;
2355 case WLAN_CATEGORY_SELF_PROTECTED: 2380 case WLAN_CATEGORY_SELF_PROTECTED:
2381 if (len < (IEEE80211_MIN_ACTION_SIZE +
2382 sizeof(mgmt->u.action.u.self_prot.action_code)))
2383 break;
2384
2356 switch (mgmt->u.action.u.self_prot.action_code) { 2385 switch (mgmt->u.action.u.self_prot.action_code) {
2357 case WLAN_SP_MESH_PEERING_OPEN: 2386 case WLAN_SP_MESH_PEERING_OPEN:
2358 case WLAN_SP_MESH_PEERING_CLOSE: 2387 case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2371 } 2400 }
2372 break; 2401 break;
2373 case WLAN_CATEGORY_MESH_ACTION: 2402 case WLAN_CATEGORY_MESH_ACTION:
2403 if (len < (IEEE80211_MIN_ACTION_SIZE +
2404 sizeof(mgmt->u.action.u.mesh_action.action_code)))
2405 break;
2406
2374 if (!ieee80211_vif_is_mesh(&sdata->vif)) 2407 if (!ieee80211_vif_is_mesh(&sdata->vif))
2375 break; 2408 break;
2376 if (mesh_action_is_path_sel(mgmt) && 2409 if (mesh_action_is_path_sel(mgmt) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2913 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) 2946 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
2914 local->dot11ReceivedFragmentCount++; 2947 local->dot11ReceivedFragmentCount++;
2915 2948
2916 if (ieee80211_is_mgmt(fc)) 2949 if (ieee80211_is_mgmt(fc)) {
2917 err = skb_linearize(skb); 2950 /* drop frame if too short for header */
2918 else 2951 if (skb->len < ieee80211_hdrlen(fc))
2952 err = -ENOBUFS;
2953 else
2954 err = skb_linearize(skb);
2955 } else {
2919 err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); 2956 err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
2957 }
2920 2958
2921 if (err) { 2959 if (err) {
2922 dev_kfree_skb(skb); 2960 dev_kfree_skb(skb);