aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h9
-rw-r--r--net/mac80211/rx.c32
-rw-r--r--net/wireless/util.c3
3 files changed, 42 insertions, 2 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f8cd4cf3fad8..7d5b6000378b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2652,6 +2652,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
2652unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); 2652unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
2653 2653
2654/** 2654/**
2655 * ieee80211_get_mesh_hdrlen - get mesh extension header length
2656 * @meshhdr: the mesh extension header, only the flags field
2657 * (first byte) will be accessed
2658 * Returns the length of the extension header, which is always at
2659 * least 6 bytes and at most 18 if address 5 and 6 are present.
2660 */
2661unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
2662
2663/**
2655 * DOC: Data path helpers 2664 * DOC: Data path helpers
2656 * 2665 *
2657 * In addition to generic utilities, cfg80211 also offers 2666 * In addition to generic utilities, cfg80211 also offers
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 99cdee16e31b..265a032dec49 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 &&
@@ -1892,6 +1897,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1892 1897
1893 hdr = (struct ieee80211_hdr *) skb->data; 1898 hdr = (struct ieee80211_hdr *) skb->data;
1894 hdrlen = ieee80211_hdrlen(hdr->frame_control); 1899 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1900
1901 /* make sure fixed part of mesh header is there, also checks skb len */
1902 if (!pskb_may_pull(rx->skb, hdrlen + 6))
1903 return RX_DROP_MONITOR;
1904
1905 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1906
1907 /* make sure full mesh header is there, also checks skb len */
1908 if (!pskb_may_pull(rx->skb,
1909 hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
1910 return RX_DROP_MONITOR;
1911
1912 /* reload pointers */
1913 hdr = (struct ieee80211_hdr *) skb->data;
1895 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); 1914 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1896 1915
1897 /* frame is in RMC, don't forward */ 1916 /* frame is in RMC, don't forward */
@@ -1915,9 +1934,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1915 if (is_multicast_ether_addr(hdr->addr1)) { 1934 if (is_multicast_ether_addr(hdr->addr1)) {
1916 mpp_addr = hdr->addr3; 1935 mpp_addr = hdr->addr3;
1917 proxied_addr = mesh_hdr->eaddr1; 1936 proxied_addr = mesh_hdr->eaddr1;
1918 } else { 1937 } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
1938 /* has_a4 already checked in ieee80211_rx_mesh_check */
1919 mpp_addr = hdr->addr4; 1939 mpp_addr = hdr->addr4;
1920 proxied_addr = mesh_hdr->eaddr2; 1940 proxied_addr = mesh_hdr->eaddr2;
1941 } else {
1942 return RX_DROP_MONITOR;
1921 } 1943 }
1922 1944
1923 rcu_read_lock(); 1945 rcu_read_lock();
@@ -2354,6 +2376,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2354 } 2376 }
2355 break; 2377 break;
2356 case WLAN_CATEGORY_SELF_PROTECTED: 2378 case WLAN_CATEGORY_SELF_PROTECTED:
2379 if (len < (IEEE80211_MIN_ACTION_SIZE +
2380 sizeof(mgmt->u.action.u.self_prot.action_code)))
2381 break;
2382
2357 switch (mgmt->u.action.u.self_prot.action_code) { 2383 switch (mgmt->u.action.u.self_prot.action_code) {
2358 case WLAN_SP_MESH_PEERING_OPEN: 2384 case WLAN_SP_MESH_PEERING_OPEN:
2359 case WLAN_SP_MESH_PEERING_CLOSE: 2385 case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2372,6 +2398,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2372 } 2398 }
2373 break; 2399 break;
2374 case WLAN_CATEGORY_MESH_ACTION: 2400 case WLAN_CATEGORY_MESH_ACTION:
2401 if (len < (IEEE80211_MIN_ACTION_SIZE +
2402 sizeof(mgmt->u.action.u.mesh_action.action_code)))
2403 break;
2404
2375 if (!ieee80211_vif_is_mesh(&sdata->vif)) 2405 if (!ieee80211_vif_is_mesh(&sdata->vif))
2376 break; 2406 break;
2377 if (mesh_action_is_path_sel(mgmt) && 2407 if (mesh_action_is_path_sel(mgmt) &&
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 45a09de1ffe3..2762e8329986 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -309,7 +309,7 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
309} 309}
310EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); 310EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
311 311
312static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) 312unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
313{ 313{
314 int ae = meshhdr->flags & MESH_FLAGS_AE; 314 int ae = meshhdr->flags & MESH_FLAGS_AE;
315 /* 802.11-2012, 8.2.4.7.3 */ 315 /* 802.11-2012, 8.2.4.7.3 */
@@ -323,6 +323,7 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
323 return 18; 323 return 18;
324 } 324 }
325} 325}
326EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
326 327
327int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, 328int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
328 enum nl80211_iftype iftype) 329 enum nl80211_iftype iftype)