diff options
Diffstat (limited to 'net/mac80211/rx.c')
| -rw-r--r-- | net/mac80211/rx.c | 33 | 
1 files changed, 27 insertions, 6 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4454ec47283f..22a925899a9e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2531,13 +2531,13 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)  	struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;  	/* -	 * Allow EAPOL frames to us/the PAE group address regardless -	 * of whether the frame was encrypted or not. +	 * Allow EAPOL frames to us/the PAE group address regardless of +	 * whether the frame was encrypted or not, and always disallow +	 * all other destination addresses for them.  	 */ -	if (ehdr->h_proto == rx->sdata->control_port_protocol && -	    (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || -	     ether_addr_equal(ehdr->h_dest, pae_group_addr))) -		return true; +	if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol)) +		return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || +		       ether_addr_equal(ehdr->h_dest, pae_group_addr);  	if (ieee80211_802_1x_port_control(rx) ||  	    ieee80211_drop_unencrypted(rx, fc)) @@ -2562,8 +2562,28 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,  		cfg80211_rx_control_port(dev, skb, noencrypt);  		dev_kfree_skb(skb);  	} else { +		struct ethhdr *ehdr = (void *)skb_mac_header(skb); +  		memset(skb->cb, 0, sizeof(skb->cb)); +		/* +		 * 802.1X over 802.11 requires that the authenticator address +		 * be used for EAPOL frames. However, 802.1X allows the use of +		 * the PAE group address instead. If the interface is part of +		 * a bridge and we pass the frame with the PAE group address, +		 * then the bridge will forward it to the network (even if the +		 * client was not associated yet), which isn't supposed to +		 * happen. +		 * To avoid that, rewrite the destination address to our own +		 * address, so that the authenticator (e.g. hostapd) will see +		 * the frame, but bridge won't forward it anywhere else. Note +		 * that due to earlier filtering, the only other address can +		 * be the PAE group address. +		 */ +		if (unlikely(skb->protocol == sdata->control_port_protocol && +			     !ether_addr_equal(ehdr->h_dest, sdata->vif.addr))) +			ether_addr_copy(ehdr->h_dest, sdata->vif.addr); +  		/* deliver to local stack */  		if (rx->list)  			list_add_tail(&skb->list, rx->list); @@ -2603,6 +2623,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)  	if ((sdata->vif.type == NL80211_IFTYPE_AP ||  	     sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&  	    !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && +	    ehdr->h_proto != rx->sdata->control_port_protocol &&  	    (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {  		if (is_multicast_ether_addr(ehdr->h_dest) &&  		    ieee80211_vif_get_num_mcast_if(sdata) != 0) {  | 
