History

net: prevent torn reads in netdev_tc_txq

netdev_set_tc_queue() (and related helpers/drivers such as netdev_bind_sb_channel_queue(), netdev_reset_tc(), and netdev_unbind_sb_channel()) perform separate 16-bit writes to dev->tc_to_txq[tc].count and dev->tc_to_txq[tc].offset. Furthermore, memset() in netdev_reset_tc() and netdev_unbind_sb_channel() provides no guarantee of performing full 32-bit word stores. Concurrent lockless readers (e.g. skb_tx_hash(), netdev_txq_to_tc(), ixgbe_select_queue(), taprio, mqprio, FPE drivers) can observe torn values where offset and count belong to inconsistent configurations. Redefine struct netdev_tc_txq to embed count and offset inside a union with a u32 combined field, allowing atomic manipulation via READ_ONCE() and WRITE_ONCE(). Update all lockless readers and writers across the kernel to use READ_ONCE() and WRITE_ONCE() on the combined field.

Eric Dumazet committed 3 months ago

Commit 21ef2d01 parent e6a5d5711 files · +94 −43Browse files

Showing the changes to include (1 of 11 files). Show all

Unified · Split

include/linux/netdevice.h+7−2
@@ -832,8 +832,13 @@ struct xps_dev_maps { · 831 unmodified lines
832832 #define TC_BITMASK 15
833833 /* HW offloaded queuing disciplines txq count and offset maps */
834834 struct netdev_tc_txq {
835− u16 count;
836− u16 offset;
835+ union {
836+ struct {
837+ u16 count;
838+ u16 offset;
839+ };
840+ u32 combined;
841+ };
837842 };
838843
839844 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t