diff options
author | Rajkumar Manoharan <rmanohar@qti.qualcomm.com> | 2017-05-15 00:41:55 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2017-05-17 08:24:29 -0400 |
commit | 5667c86acf021e6dcf02584408b4484a273ac68f (patch) | |
tree | 0fa26498af9173f5eddfe41f2ca81a6689fc6963 | |
parent | 29cee56c0be46ad01e78af104a06223c65ee0c67 (diff) |
mac80211: strictly check mesh address extension mode
Mesh forwarding path checks for address extension mode to fetch
appropriate proxied address and MPP address. Existing condition
that looks for 6 address format is not strict enough so that
frames with improper values are processed and invalid entries
are added into MPP table. Fix that by adding a stricter check before
processing the packet.
Per IEEE Std 802.11s-2011 spec. Table 7-6g1 lists address extension
mode 0x3 as reserved one. And also Table Table 9-13 does not specify
0x3 as valid address field.
Fixes: 9b395bc3be1c ("mac80211: verify that skb data is present")
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/rx.c | 3 | ||||
-rw-r--r-- | net/wireless/util.c | 10 |
2 files changed, 8 insertions, 5 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 35f4c7d7a500..1f75280ba26c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2492,7 +2492,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2492 | if (is_multicast_ether_addr(hdr->addr1)) { | 2492 | if (is_multicast_ether_addr(hdr->addr1)) { |
2493 | mpp_addr = hdr->addr3; | 2493 | mpp_addr = hdr->addr3; |
2494 | proxied_addr = mesh_hdr->eaddr1; | 2494 | proxied_addr = mesh_hdr->eaddr1; |
2495 | } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { | 2495 | } else if ((mesh_hdr->flags & MESH_FLAGS_AE) == |
2496 | MESH_FLAGS_AE_A5_A6) { | ||
2496 | /* has_a4 already checked in ieee80211_rx_mesh_check */ | 2497 | /* has_a4 already checked in ieee80211_rx_mesh_check */ |
2497 | mpp_addr = hdr->addr4; | 2498 | mpp_addr = hdr->addr4; |
2498 | proxied_addr = mesh_hdr->eaddr2; | 2499 | proxied_addr = mesh_hdr->eaddr2; |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 7198373e2920..4992f1025c9d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -454,6 +454,8 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, | |||
454 | if (iftype == NL80211_IFTYPE_MESH_POINT) | 454 | if (iftype == NL80211_IFTYPE_MESH_POINT) |
455 | skb_copy_bits(skb, hdrlen, &mesh_flags, 1); | 455 | skb_copy_bits(skb, hdrlen, &mesh_flags, 1); |
456 | 456 | ||
457 | mesh_flags &= MESH_FLAGS_AE; | ||
458 | |||
457 | switch (hdr->frame_control & | 459 | switch (hdr->frame_control & |
458 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 460 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
459 | case cpu_to_le16(IEEE80211_FCTL_TODS): | 461 | case cpu_to_le16(IEEE80211_FCTL_TODS): |
@@ -469,9 +471,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, | |||
469 | iftype != NL80211_IFTYPE_STATION)) | 471 | iftype != NL80211_IFTYPE_STATION)) |
470 | return -1; | 472 | return -1; |
471 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 473 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
472 | if (mesh_flags & MESH_FLAGS_AE_A4) | 474 | if (mesh_flags == MESH_FLAGS_AE_A4) |
473 | return -1; | 475 | return -1; |
474 | if (mesh_flags & MESH_FLAGS_AE_A5_A6) { | 476 | if (mesh_flags == MESH_FLAGS_AE_A5_A6) { |
475 | skb_copy_bits(skb, hdrlen + | 477 | skb_copy_bits(skb, hdrlen + |
476 | offsetof(struct ieee80211s_hdr, eaddr1), | 478 | offsetof(struct ieee80211s_hdr, eaddr1), |
477 | tmp.h_dest, 2 * ETH_ALEN); | 479 | tmp.h_dest, 2 * ETH_ALEN); |
@@ -487,9 +489,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, | |||
487 | ether_addr_equal(tmp.h_source, addr))) | 489 | ether_addr_equal(tmp.h_source, addr))) |
488 | return -1; | 490 | return -1; |
489 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 491 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
490 | if (mesh_flags & MESH_FLAGS_AE_A5_A6) | 492 | if (mesh_flags == MESH_FLAGS_AE_A5_A6) |
491 | return -1; | 493 | return -1; |
492 | if (mesh_flags & MESH_FLAGS_AE_A4) | 494 | if (mesh_flags == MESH_FLAGS_AE_A4) |
493 | skb_copy_bits(skb, hdrlen + | 495 | skb_copy_bits(skb, hdrlen + |
494 | offsetof(struct ieee80211s_hdr, eaddr1), | 496 | offsetof(struct ieee80211s_hdr, eaddr1), |
495 | tmp.h_source, ETH_ALEN); | 497 | tmp.h_source, ETH_ALEN); |