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 c0a1f53e68ab..38b382682cae 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -525,6 +525,11 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
525 525
526 if (ieee80211_is_action(hdr->frame_control)) { 526 if (ieee80211_is_action(hdr->frame_control)) {
527 u8 category; 527 u8 category;
528
529 /* make sure category field is present */
530 if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
531 return RX_DROP_MONITOR;
532
528 mgmt = (struct ieee80211_mgmt *)hdr; 533 mgmt = (struct ieee80211_mgmt *)hdr;
529 category = mgmt->u.action.category; 534 category = mgmt->u.action.category;
530 if (category != WLAN_CATEGORY_MESH_ACTION && 535 if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -875,14 +880,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
875 */ 880 */
876 if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && 881 if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
877 ieee80211_is_data_present(hdr->frame_control)) { 882 ieee80211_is_data_present(hdr->frame_control)) {
878 u16 ethertype; 883 unsigned int hdrlen;
879 u8 *payload; 884 __be16 ethertype;
880 885
881 payload = rx->skb->data + 886 hdrlen = ieee80211_hdrlen(hdr->frame_control);
882 ieee80211_hdrlen(hdr->frame_control); 887
883 ethertype = (payload[6] << 8) | payload[7]; 888 if (rx->skb->len < hdrlen + 8)
884 if (cpu_to_be16(ethertype) == 889 return RX_DROP_MONITOR;
885 rx->sdata->control_port_protocol) 890
891 skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
892 if (ethertype == rx->sdata->control_port_protocol)
886 return RX_CONTINUE; 893 return RX_CONTINUE;
887 } 894 }
888 895
@@ -1459,11 +1466,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
1459 1466
1460 hdr = (struct ieee80211_hdr *)rx->skb->data; 1467 hdr = (struct ieee80211_hdr *)rx->skb->data;
1461 fc = hdr->frame_control; 1468 fc = hdr->frame_control;
1469
1470 if (ieee80211_is_ctl(fc))
1471 return RX_CONTINUE;
1472
1462 sc = le16_to_cpu(hdr->seq_ctrl); 1473 sc = le16_to_cpu(hdr->seq_ctrl);
1463 frag = sc & IEEE80211_SCTL_FRAG; 1474 frag = sc & IEEE80211_SCTL_FRAG;
1464 1475
1465 if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || 1476 if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
1466 (rx->skb)->len < 24 ||
1467 is_multicast_ether_addr(hdr->addr1))) { 1477 is_multicast_ether_addr(hdr->addr1))) {
1468 /* not fragmented */ 1478 /* not fragmented */
1469 goto out; 1479 goto out;
@@ -1882,6 +1892,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1882 1892
1883 hdr = (struct ieee80211_hdr *) skb->data; 1893 hdr = (struct ieee80211_hdr *) skb->data;
1884 hdrlen = ieee80211_hdrlen(hdr->frame_control); 1894 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1895
1896 /* make sure fixed part of mesh header is there, also checks skb len */
1897 if (!pskb_may_pull(rx->skb, hdrlen + 6))
1898 return RX_DROP_MONITOR;
1899
1900 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1901
1902 /* make sure full mesh header is there, also checks skb len */
1903 if (!pskb_may_pull(rx->skb,
1904 hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
1905 return RX_DROP_MONITOR;
1906
1907 /* reload pointers */
1908 hdr = (struct ieee80211_hdr *) skb->data;
1885 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); 1909 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1886 1910
1887 /* frame is in RMC, don't forward */ 1911 /* frame is in RMC, don't forward */
@@ -1890,7 +1914,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1890 mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) 1914 mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
1891 return RX_DROP_MONITOR; 1915 return RX_DROP_MONITOR;
1892 1916
1893 if (!ieee80211_is_data(hdr->frame_control)) 1917 if (!ieee80211_is_data(hdr->frame_control) ||
1918 !(status->rx_flags & IEEE80211_RX_RA_MATCH))
1894 return RX_CONTINUE; 1919 return RX_CONTINUE;
1895 1920
1896 if (!mesh_hdr->ttl) 1921 if (!mesh_hdr->ttl)
@@ -1904,9 +1929,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1904 if (is_multicast_ether_addr(hdr->addr1)) { 1929 if (is_multicast_ether_addr(hdr->addr1)) {
1905 mpp_addr = hdr->addr3; 1930 mpp_addr = hdr->addr3;
1906 proxied_addr = mesh_hdr->eaddr1; 1931 proxied_addr = mesh_hdr->eaddr1;
1907 } else { 1932 } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
1933 /* has_a4 already checked in ieee80211_rx_mesh_check */
1908 mpp_addr = hdr->addr4; 1934 mpp_addr = hdr->addr4;
1909 proxied_addr = mesh_hdr->eaddr2; 1935 proxied_addr = mesh_hdr->eaddr2;
1936 } else {
1937 return RX_DROP_MONITOR;
1910 } 1938 }
1911 1939
1912 rcu_read_lock(); 1940 rcu_read_lock();
@@ -1934,12 +1962,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1934 } 1962 }
1935 skb_set_queue_mapping(skb, q); 1963 skb_set_queue_mapping(skb, q);
1936 1964
1937 if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
1938 goto out;
1939
1940 if (!--mesh_hdr->ttl) { 1965 if (!--mesh_hdr->ttl) {
1941 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); 1966 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
1942 return RX_DROP_MONITOR; 1967 goto out;
1943 } 1968 }
1944 1969
1945 if (!ifmsh->mshcfg.dot11MeshForwarding) 1970 if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2346,6 +2371,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2346 } 2371 }
2347 break; 2372 break;
2348 case WLAN_CATEGORY_SELF_PROTECTED: 2373 case WLAN_CATEGORY_SELF_PROTECTED:
2374 if (len < (IEEE80211_MIN_ACTION_SIZE +
2375 sizeof(mgmt->u.action.u.self_prot.action_code)))
2376 break;
2377
2349 switch (mgmt->u.action.u.self_prot.action_code) { 2378 switch (mgmt->u.action.u.self_prot.action_code) {
2350 case WLAN_SP_MESH_PEERING_OPEN: 2379 case WLAN_SP_MESH_PEERING_OPEN:
2351 case WLAN_SP_MESH_PEERING_CLOSE: 2380 case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2364,6 +2393,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2364 } 2393 }
2365 break; 2394 break;
2366 case WLAN_CATEGORY_MESH_ACTION: 2395 case WLAN_CATEGORY_MESH_ACTION:
2396 if (len < (IEEE80211_MIN_ACTION_SIZE +
2397 sizeof(mgmt->u.action.u.mesh_action.action_code)))
2398 break;
2399
2367 if (!ieee80211_vif_is_mesh(&sdata->vif)) 2400 if (!ieee80211_vif_is_mesh(&sdata->vif))
2368 break; 2401 break;
2369 if (mesh_action_is_path_sel(mgmt) && 2402 if (mesh_action_is_path_sel(mgmt) &&
@@ -2905,10 +2938,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2905 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) 2938 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
2906 local->dot11ReceivedFragmentCount++; 2939 local->dot11ReceivedFragmentCount++;
2907 2940
2908 if (ieee80211_is_mgmt(fc)) 2941 if (ieee80211_is_mgmt(fc)) {
2909 err = skb_linearize(skb); 2942 /* drop frame if too short for header */
2910 else 2943 if (skb->len < ieee80211_hdrlen(fc))
2944 err = -ENOBUFS;
2945 else
2946 err = skb_linearize(skb);
2947 } else {
2911 err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); 2948 err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
2949 }
2912 2950
2913 if (err) { 2951 if (err) {
2914 dev_kfree_skb(skb); 2952 dev_kfree_skb(skb);