9a0b78def1939ddf4ce97a0825674f83f11b2ca2
[openwrt/staging/robimarko.git] /
1 From: Johannes Berg <johannes.berg@intel.com>
2 Date: Tue, 11 May 2021 20:02:50 +0200
3 Subject: [PATCH] mac80211: do not accept/forward invalid EAPOL frames
4
5 EAPOL frames are used for authentication and key management between the
6 AP and each individual STA associated in the BSS. Those frames are not
7 supposed to be sent by one associated STA to another associated STA
8 (either unicast for broadcast/multicast).
9
10 Similarly, in 802.11 they're supposed to be sent to the authenticator
11 (AP) address.
12
13 Since it is possible for unexpected EAPOL frames to result in misbehavior
14 in supplicant implementations, it is better for the AP to not allow such
15 cases to be forwarded to other clients either directly, or indirectly if
16 the AP interface is part of a bridge.
17
18 Accept EAPOL (control port) frames only if they're transmitted to the
19 own address, or, due to interoperability concerns, to the PAE group
20 address.
21
22 Disable forwarding of EAPOL (or well, the configured control port
23 protocol) frames back to wireless medium in all cases. Previously, these
24 frames were accepted from fully authenticated and authorized stations
25 and also from unauthenticated stations for one of the cases.
26
27 Additionally, to avoid forwarding by the bridge, rewrite the PAE group
28 address case to the local MAC address.
29
30 Cc: stable@vger.kernel.org
31 Co-developed-by: Jouni Malinen <jouni@codeaurora.org>
32 Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
33 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
34 ---
35
36 --- a/net/mac80211/rx.c
37 +++ b/net/mac80211/rx.c
38 @@ -2541,13 +2541,13 @@ static bool ieee80211_frame_allowed(stru
39 struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
40
41 /*
42 - * Allow EAPOL frames to us/the PAE group address regardless
43 - * of whether the frame was encrypted or not.
44 + * Allow EAPOL frames to us/the PAE group address regardless of
45 + * whether the frame was encrypted or not, and always disallow
46 + * all other destination addresses for them.
47 */
48 - if (ehdr->h_proto == rx->sdata->control_port_protocol &&
49 - (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
50 - ether_addr_equal(ehdr->h_dest, pae_group_addr)))
51 - return true;
52 + if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol))
53 + return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
54 + ether_addr_equal(ehdr->h_dest, pae_group_addr);
55
56 if (ieee80211_802_1x_port_control(rx) ||
57 ieee80211_drop_unencrypted(rx, fc))
58 @@ -2572,8 +2572,28 @@ static void ieee80211_deliver_skb_to_loc
59 cfg80211_rx_control_port(dev, skb, noencrypt);
60 dev_kfree_skb(skb);
61 } else {
62 + struct ethhdr *ehdr = (void *)skb_mac_header(skb);
63 +
64 memset(skb->cb, 0, sizeof(skb->cb));
65
66 + /*
67 + * 802.1X over 802.11 requires that the authenticator address
68 + * be used for EAPOL frames. However, 802.1X allows the use of
69 + * the PAE group address instead. If the interface is part of
70 + * a bridge and we pass the frame with the PAE group address,
71 + * then the bridge will forward it to the network (even if the
72 + * client was not associated yet), which isn't supposed to
73 + * happen.
74 + * To avoid that, rewrite the destination address to our own
75 + * address, so that the authenticator (e.g. hostapd) will see
76 + * the frame, but bridge won't forward it anywhere else. Note
77 + * that due to earlier filtering, the only other address can
78 + * be the PAE group address.
79 + */
80 + if (unlikely(skb->protocol == sdata->control_port_protocol &&
81 + !ether_addr_equal(ehdr->h_dest, sdata->vif.addr)))
82 + ether_addr_copy(ehdr->h_dest, sdata->vif.addr);
83 +
84 /* deliver to local stack */
85 if (rx->list)
86 #if LINUX_VERSION_IS_GEQ(4,19,0)
87 @@ -2617,6 +2637,7 @@ ieee80211_deliver_skb(struct ieee80211_r
88 if ((sdata->vif.type == NL80211_IFTYPE_AP ||
89 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
90 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
91 + ehdr->h_proto != rx->sdata->control_port_protocol &&
92 (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
93 if (is_multicast_ether_addr(ehdr->h_dest) &&
94 ieee80211_vif_get_num_mcast_if(sdata) != 0) {