[PATCH net-next 0/3] net: prevent lockless data races in net_device TC structures
Eric Dumazet <[email protected]>
| Newsgroups | org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
This patch series resolves lockless data races between fast-path packet
processing / qdisc schedulers (e.g. taprio advance_sched(), XPS queue
lookups, skb_tx_hash()) and control-path updates modifying traffic class
configurations on a net_device.
syzbot / KCSAN reported a data-race between advance_sched() reading
dev->num_tc in netdev_get_num_tc() and control-path updates writing
dev->num_tc in netdev_set_num_tc():
==================================================================
BUG: KCSAN: data-race in advance_sched / netdev_set_num_tc
write to 0xffff88811ac5c036 of 2 bytes by task 4434 on cpu 0:
netdev_set_num_tc+0x... net/core/dev.c:3158
...
tc_modify_qdisc+0x102a/0x1550 net/sched/sch_api.c:1844
rtnetlink_rcv_msg+0x6a7/0x720 net/core/rtnetlink.c:7085
read to 0xffff88811ac5c036 of 2 bytes by interrupt on cpu 1:
netdev_get_num_tc include/linux/netdevice.h:2684 [inline]
taprio_set_budgets net/sched/sch_taprio.c:667 [inline]
advance_sched+0x58f/0x730 net/sched/sch_taprio.c:984
__run_hrtimer kernel/time/hrtimer.c:2032 [inline]
__hrtimer_run_queues+0x1f8/0x510 kernel/time/hrtimer.c:2096
value changed: 0x0000 -> 0x0001
==================================================================
Further inspection of the TC metadata structures on struct net_device
revealed three separate issues under concurrent lockless access:
1. struct netdev_tc_txq holds adjacent 16-bit offset and count fields
that are written separately in netdev_set_tc_queue() (and cleared
via memset() during reset), allowing lockless readers in fast-path
helpers and drivers to observe torn/inconsistent states. This is fixed
in Patch 1 by wrapping count and offset in a union with a u32
combined field manipulated atomically via READ_ONCE()/WRITE_ONCE().
2. dev->num_tc is read locklessly in fast-path lookups and timer
interrupts without READ_ONCE() annotations, while control paths modify
it using plain writes. Patch 2 adds READ_ONCE()/WRITE_ONCE()
annotations across core networking code and drivers.
3. dev->prio_tc_map is similarly read locklessly in fast-path helpers
such as skb_tx_hash() while control paths update entries or clear the
map via memset(). Patch 3 adds READ_ONCE()/WRITE_ONCE() annotations
to netdev_get_prio_tc_map() and netdev_set_prio_tc_map() and replaces
memset() with explicit atomic store loops.
Reported-by: [email protected]
Closes: https://lore.kernel.org/netdev/[email protected]/T/#u
Eric Dumazet (3):
net: prevent torn reads in netdev_tc_txq
net: add READ_ONCE()/WRITE_ONCE() annotations for dev->num_tc
net: add READ_ONCE()/WRITE_ONCE() annotations for dev->prio_tc_map
.../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +-
.../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 12 +--
drivers/net/ethernet/intel/igc/igc_tsn.c | 8 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 7 +-
.../net/ethernet/mellanox/mlx5/core/en_main.c | 4 +-
drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +-
drivers/net/ethernet/sfc/falcon/tx.c | 16 ++--
drivers/net/ethernet/sfc/siena/tx.c | 12 ++-
.../net/ethernet/stmicro/stmmac/stmmac_fpe.c | 14 +++-
drivers/net/ethernet/ti/cpsw_priv.c | 2 +-
include/linux/netdevice.h | 21 +++--
net/core/dev.c | 77 ++++++++++++-------
net/core/net-sysfs.c | 2 +-
net/sched/sch_mqprio.c | 4 +-
net/sched/sch_mqprio_lib.c | 10 ++-
net/sched/sch_taprio.c | 35 +++++----
16 files changed, 143 insertions(+), 85 deletions(-)
--
2.55.0.679.g6767b8d81c-goog