[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.