Re: [PATCH] can: vcan: use per-CPU device stats

From: Marc Kleine-Budde

Date: Wed Oct 07 2026 - 09:33:36 EST


On 07.10.2026 17:06:11, Yogesh Gaur wrote:
> vcan_tx() and vcan_rx() update dev->stats with plain increments and
> rely on the tx queue lock to serialise them. That only holds for a
> single tx queue. vcan does not implement get_num_tx_queues(), so
> rtnl_create_link() honours IFLA_NUM_TX_QUEUES and a vcan device can be
> created with several queues, each with its own xmit lock. Two CPUs
> transmitting on different queues then update the same counters
> concurrently and lose increments:
>
> BUG: KCSAN: data-race in vcan_tx / vcan_tx
> read-write to 0xffff88811aad8228 of 8 bytes by interrupt on cpu 1:
> vcan_tx+0x325/0x5d0 drivers/net/can/vcan.c:110
> dev_hard_start_xmit+0x10c/0x380 net/core/dev.c:3969
> __dev_queue_xmit+0xbfd/0x1ec0 net/core/dev.c:4958
> can_send+0x584/0x720 net/can/af_can.c:279
> bcm_can_tx+0x3ba/0x5b0 net/can/bcm.c:367
> read-write to 0xffff88811aad8228 of 8 bytes by interrupt on cpu 0:
> vcan_tx+0x325/0x5d0 drivers/net/can/vcan.c:110
> value changed: 0x00000000000025ef -> 0x00000000000025f0
>
> Switch the packet and byte counters to the core's per-CPU dstats.
> The core allocates them for NETDEV_PCPU_STAT_DSTATS and folds them
> together with dev->stats in dev_get_stats(), so tx_dropped from
> can_dropped_invalid_skb() is still reported.
>
> Reported-by: syzbot+937a3a1fbfbc99d6fcaf@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=937a3a1fbfbc99d6fcaf
> Assisted-by: LLM
> Signed-off-by: Yogesh Gaur <yogeshgaur.83@xxxxxxxxx>

So far all drivers use the classic stats, and the CAN dev helper code
(in drivers/net/can/dev) also modifies these fields. A quick search
shows these places:

drivers/net/can/dev/rx-offload.c:48: struct net_device_stats *stats = &dev->stats;
drivers/net/can/dev/rx-offload.c:162: offload->dev->stats.rx_dropped++;
drivers/net/can/dev/rx-offload.c:163: offload->dev->stats.rx_fifo_errors++;
drivers/net/can/dev/rx-offload.c:249: struct net_device_stats *stats = &dev->stats;
drivers/net/can/dev/rx-offload.c:289: struct net_device_stats *stats = &dev->stats;
drivers/net/can/dev/skb.c:29: struct net_device_stats *stats = &dev->stats;
drivers/net/can/dev/skb.c:402: dev->stats.tx_dropped++;

Can you modify the code to update the dstats if they are active?

regards,
Marc

--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |

Attachment: signature.asc
Description: PGP signature