diff options
Diffstat (limited to 'drivers/net/macsec.c')
| -rw-r--r-- | drivers/net/macsec.c | 48 | 
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 0206b84284ab..2da70bc3dd86 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -999,10 +999,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)  	struct metadata_dst *md_dst;  	struct macsec_rxh_data *rxd;  	struct macsec_dev *macsec; +	bool is_macsec_md_dst;  	rcu_read_lock();  	rxd = macsec_data_rcu(skb->dev);  	md_dst = skb_metadata_dst(skb); +	is_macsec_md_dst = md_dst && md_dst->type == METADATA_MACSEC;  	list_for_each_entry_rcu(macsec, &rxd->secys, secys) {  		struct sk_buff *nskb; @@ -1013,14 +1015,42 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)  		 * the SecTAG, so we have to deduce which port to deliver to.  		 */  		if (macsec_is_offloaded(macsec) && netif_running(ndev)) { -			struct macsec_rx_sc *rx_sc = NULL; +			const struct macsec_ops *ops; -			if (md_dst && md_dst->type == METADATA_MACSEC) -				rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci); +			ops = macsec_get_ops(macsec, NULL); -			if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc) +			if (ops->rx_uses_md_dst && !is_macsec_md_dst)  				continue; +			if (is_macsec_md_dst) { +				struct macsec_rx_sc *rx_sc; + +				/* All drivers that implement MACsec offload +				 * support using skb metadata destinations must +				 * indicate that they do so. +				 */ +				DEBUG_NET_WARN_ON_ONCE(!ops->rx_uses_md_dst); +				rx_sc = find_rx_sc(&macsec->secy, +						   md_dst->u.macsec_info.sci); +				if (!rx_sc) +					continue; +				/* device indicated macsec offload occurred */ +				skb->dev = ndev; +				skb->pkt_type = PACKET_HOST; +				eth_skb_pkt_type(skb, ndev); +				ret = RX_HANDLER_ANOTHER; +				goto out; +			} + +			/* This datapath is insecure because it is unable to +			 * enforce isolation of broadcast/multicast traffic and +			 * unicast traffic with promiscuous mode on the macsec +			 * netdev. Since the core stack has no mechanism to +			 * check that the hardware did indeed receive MACsec +			 * traffic, it is possible that the response handling +			 * done by the MACsec port was to a plaintext packet. +			 * This violates the MACsec protocol standard. +			 */  			if (ether_addr_equal_64bits(hdr->h_dest,  						    ndev->dev_addr)) {  				/* exact match, divert skb to this port */ @@ -1036,14 +1066,10 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)  					break;  				nskb->dev = ndev; -				if (ether_addr_equal_64bits(hdr->h_dest, -							    ndev->broadcast)) -					nskb->pkt_type = PACKET_BROADCAST; -				else -					nskb->pkt_type = PACKET_MULTICAST; +				eth_skb_pkt_type(nskb, ndev);  				__netif_rx(nskb); -			} else if (rx_sc || ndev->flags & IFF_PROMISC) { +			} else if (ndev->flags & IFF_PROMISC) {  				skb->dev = ndev;  				skb->pkt_type = PACKET_HOST;  				ret = RX_HANDLER_ANOTHER; @@ -3727,7 +3753,7 @@ static int macsec_change_mtu(struct net_device *dev, int new_mtu)  	if (macsec->real_dev->mtu - extra < new_mtu)  		return -ERANGE; -	dev->mtu = new_mtu; +	WRITE_ONCE(dev->mtu, new_mtu);  	return 0;  }  |