]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
vxcan: remove sk reference in peer skb
authorOliver Hartkopp <socketcan@hartkopp.net>
Wed, 9 Mar 2022 12:04:15 +0000 (13:04 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Thu, 10 Mar 2022 08:23:45 +0000 (09:23 +0100)
With can_create_echo_skb() the skb which is forwarded to the peer CAN
interface shares the sk pointer from the originating socket.
This makes the CAN frame show up in the peer namespace as a TX packet.

With the use of skb_clone() analogue to the handling in gw.c the peer
skb gets a new start in the peer namespace and correctly appears as
a RX packet.

Link: https://lore.kernel.org/all/20220309120416.83514-4-socketcan@hartkopp.net
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/vxcan.c

index 556f1a12ec9a0786ed050f3600ba904f04162e41..51501af8d9fcd8ef49106414597361caf53b3011 100644 (file)
@@ -33,28 +33,33 @@ struct vxcan_priv {
        struct net_device __rcu *peer;
 };
 
-static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev)
 {
        struct vxcan_priv *priv = netdev_priv(dev);
        struct net_device *peer;
-       struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+       struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
        struct net_device_stats *peerstats, *srcstats = &dev->stats;
+       struct sk_buff *skb;
        u8 len;
 
-       if (can_dropped_invalid_skb(dev, skb))
+       if (can_dropped_invalid_skb(dev, oskb))
                return NETDEV_TX_OK;
 
        rcu_read_lock();
        peer = rcu_dereference(priv->peer);
        if (unlikely(!peer)) {
-               kfree_skb(skb);
+               kfree_skb(oskb);
                dev->stats.tx_dropped++;
                goto out_unlock;
        }
 
-       skb = can_create_echo_skb(skb);
-       if (!skb)
+       skb = skb_clone(oskb, GFP_ATOMIC);
+       if (skb) {
+               consume_skb(oskb);
+       } else {
+               kfree(oskb);
                goto out_unlock;
+       }
 
        /* reset CAN GW hop counter */
        skb->csum_start = 0;