Skip to content

Commit 0a65dcf

Browse files
committed
net: designate queue counts as "double ops protected" by instance lock
Drivers which opt into instance lock protection of ops should only call set_real_num_*_queues() under the instance lock. This means that queue counts are double protected (writes are under both rtnl_lock and instance lock, readers under either). Some readers may still be under the rtnl_lock, however, so for now we need double protection of writers. OTOH queue API paths are only under the protection of the instance lock, so we need to validate that the instance is actually locking ops, otherwise the input checks we do against queue count are racy. Acked-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4b702f8 commit 0a65dcf

File tree

5 files changed

+17
-0
lines changed

5 files changed

+17
-0
lines changed

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,9 @@ struct net_device {
25232523
* Double protects:
25242524
* @up
25252525
*
2526+
* Double ops protects:
2527+
* @real_num_rx_queues, @real_num_tx_queues
2528+
*
25262529
* Also protects some fields in struct napi_struct.
25272530
*
25282531
* Ordering: take after rtnl_lock.

net/core/dev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,6 +3130,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
31303130
if (dev->reg_state == NETREG_REGISTERED ||
31313131
dev->reg_state == NETREG_UNREGISTERING) {
31323132
ASSERT_RTNL();
3133+
netdev_ops_assert_locked(dev);
31333134

31343135
rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
31353136
txq);
@@ -3179,6 +3180,7 @@ int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
31793180

31803181
if (dev->reg_state == NETREG_REGISTERED) {
31813182
ASSERT_RTNL();
3183+
netdev_ops_assert_locked(dev);
31823184

31833185
rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues,
31843186
rxq);

net/core/net-sysfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,8 +2148,10 @@ static void remove_queue_kobjects(struct net_device *dev)
21482148
net_rx_queue_update_kobjects(dev, real_rx, 0);
21492149
netdev_queue_update_kobjects(dev, real_tx, 0);
21502150

2151+
netdev_lock_ops(dev);
21512152
dev->real_num_rx_queues = 0;
21522153
dev->real_num_tx_queues = 0;
2154+
netdev_unlock_ops(dev);
21532155
#ifdef CONFIG_SYSFS
21542156
kset_unregister(dev->queues_kset);
21552157
#endif

net/core/netdev-genl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,13 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
867867
goto err_unlock_sock;
868868
}
869869

870+
if (!netdev_need_ops_lock(netdev)) {
871+
err = -EOPNOTSUPP;
872+
NL_SET_BAD_ATTR(info->extack,
873+
info->attrs[NETDEV_A_DEV_IFINDEX]);
874+
goto err_unlock;
875+
}
876+
870877
if (dev_xdp_prog_count(netdev)) {
871878
NL_SET_ERR_MSG(info->extack, "unable to bind dmabuf to device with XDP program attached");
872879
err = -EEXIST;

net/core/netdev_rx_queue.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
9292
struct netdev_rx_queue *rxq;
9393
int ret;
9494

95+
if (!netdev_need_ops_lock(dev))
96+
return -EOPNOTSUPP;
97+
9598
if (ifq_idx >= dev->real_num_rx_queues)
9699
return -EINVAL;
97100
ifq_idx = array_index_nospec(ifq_idx, dev->real_num_rx_queues);

0 commit comments

Comments
 (0)