@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
531531
532532 if (ieee80211_is_action (hdr -> frame_control )) {
533533 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+
534539 mgmt = (struct ieee80211_mgmt * )hdr ;
535540 category = mgmt -> u .action .category ;
536541 if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
883888 */
884889 if (rx -> sta && rx -> sdata -> vif .type == NL80211_IFTYPE_STATION &&
885890 ieee80211_is_data_present (hdr -> frame_control )) {
886- u16 ethertype ;
887- u8 * payload ;
888-
889- payload = rx -> skb -> data +
890- ieee80211_hdrlen (hdr -> frame_control );
891- ethertype = (payload [6 ] << 8 ) | payload [7 ];
892- if (cpu_to_be16 (ethertype ) ==
893- rx -> sdata -> control_port_protocol )
891+ unsigned int hdrlen ;
892+ __be16 ethertype ;
893+
894+ hdrlen = ieee80211_hdrlen (hdr -> frame_control );
895+
896+ if (rx -> skb -> len < hdrlen + 8 )
897+ return RX_DROP_MONITOR ;
898+
899+ skb_copy_bits (rx -> skb , hdrlen + 6 , & ethertype , 2 );
900+ if (ethertype == rx -> sdata -> control_port_protocol )
894901 return RX_CONTINUE ;
895902 }
896903
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
14621469
14631470 hdr = (struct ieee80211_hdr * )rx -> skb -> data ;
14641471 fc = hdr -> frame_control ;
1472+
1473+ if (ieee80211_is_ctl (fc ))
1474+ return RX_CONTINUE ;
1475+
14651476 sc = le16_to_cpu (hdr -> seq_ctrl );
14661477 frag = sc & IEEE80211_SCTL_FRAG ;
14671478
14681479 if (likely ((!ieee80211_has_morefrags (fc ) && frag == 0 ) ||
1469- (rx -> skb )-> len < 24 ||
14701480 is_multicast_ether_addr (hdr -> addr1 ))) {
14711481 /* not fragmented */
14721482 goto out ;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
18891899
18901900 hdr = (struct ieee80211_hdr * ) skb -> data ;
18911901 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 ;
18921916 mesh_hdr = (struct ieee80211s_hdr * ) (skb -> data + hdrlen );
18931917
18941918 /* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
18971921 mesh_rmc_check (hdr -> addr3 , mesh_hdr , rx -> sdata ))
18981922 return RX_DROP_MONITOR ;
18991923
1900- if (!ieee80211_is_data (hdr -> frame_control ))
1924+ if (!ieee80211_is_data (hdr -> frame_control ) ||
1925+ !(status -> rx_flags & IEEE80211_RX_RA_MATCH ))
19011926 return RX_CONTINUE ;
19021927
19031928 if (!mesh_hdr -> ttl )
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
19111936 if (is_multicast_ether_addr (hdr -> addr1 )) {
19121937 mpp_addr = hdr -> addr3 ;
19131938 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 */
19151941 mpp_addr = hdr -> addr4 ;
19161942 proxied_addr = mesh_hdr -> eaddr2 ;
1943+ } else {
1944+ return RX_DROP_MONITOR ;
19171945 }
19181946
19191947 rcu_read_lock ();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
19411969 }
19421970 skb_set_queue_mapping (skb , q );
19431971
1944- if (!(status -> rx_flags & IEEE80211_RX_RA_MATCH ))
1945- goto out ;
1946-
19471972 if (!-- mesh_hdr -> ttl ) {
19481973 IEEE80211_IFSTA_MESH_CTR_INC (ifmsh , dropped_frames_ttl );
1949- return RX_DROP_MONITOR ;
1974+ goto out ;
19501975 }
19511976
19521977 if (!ifmsh -> mshcfg .dot11MeshForwarding )
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
23532378 }
23542379 break ;
23552380 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+
23562385 switch (mgmt -> u .action .u .self_prot .action_code ) {
23572386 case WLAN_SP_MESH_PEERING_OPEN :
23582387 case WLAN_SP_MESH_PEERING_CLOSE :
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
23712400 }
23722401 break ;
23732402 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+
23742407 if (!ieee80211_vif_is_mesh (& sdata -> vif ))
23752408 break ;
23762409 if (mesh_action_is_path_sel (mgmt ) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
29132946 if (ieee80211_is_data (fc ) || ieee80211_is_mgmt (fc ))
29142947 local -> dot11ReceivedFragmentCount ++ ;
29152948
2916- if (ieee80211_is_mgmt (fc ))
2917- err = skb_linearize (skb );
2918- else
2949+ if (ieee80211_is_mgmt (fc )) {
2950+ /* drop frame if too short for header */
2951+ if (skb -> len < ieee80211_hdrlen (fc ))
2952+ err = - ENOBUFS ;
2953+ else
2954+ err = skb_linearize (skb );
2955+ } else {
29192956 err = !pskb_may_pull (skb , ieee80211_hdrlen (fc ));
2957+ }
29202958
29212959 if (err ) {
29222960 dev_kfree_skb (skb );
0 commit comments