]> git.itanic.dy.fi Git - linux-stable/commitdiff
macsec: Detect if Rx skb is macsec-related for offloading devices that update md_dst
authorRahul Rameshbabu <rrameshbabu@nvidia.com>
Tue, 23 Apr 2024 18:13:04 +0000 (11:13 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 25 Apr 2024 15:20:54 +0000 (08:20 -0700)
Can now correctly identify where the packets should be delivered by using
md_dst or its absence on devices that provide it.

This detection is not possible without device drivers that update md_dst. A
fallback pattern should be used for supporting such device drivers. This
fallback mode causes multicast messages to be cloned to both the non-macsec
and macsec ports, independent of whether the multicast message received was
encrypted over MACsec or not. Other non-macsec traffic may also fail to be
handled correctly for devices in promiscuous mode.

Link: https://lore.kernel.org/netdev/ZULRxX9eIbFiVi7v@hog/
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: stable@vger.kernel.org
Fixes: 860ead89b851 ("net/macsec: Add MACsec skb_metadata_dst Rx Data path support")
Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Reviewed-by: Benjamin Poirier <bpoirier@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://lore.kernel.org/r/20240423181319.115860-4-rrameshbabu@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/macsec.c

index 0206b84284ab5e0c95981ff86fa4b2a2a14c5c51..ff016c11b4a0383b6653a37ef4bc6344fff3f703 100644 (file)
@@ -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;