Skip to content

Commit 97246d6

Browse files
Stanislav Fomichevkuba-moo
authored andcommitted
net: hold netdev instance lock during ndo_bpf
Cover the paths that come via bpf system call and XSK bind. Cc: Saeed Mahameed <[email protected]> Signed-off-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ad7c7b2 commit 97246d6

File tree

6 files changed

+33
-4
lines changed

6 files changed

+33
-4
lines changed

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4277,6 +4277,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
42774277

42784278
int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
42794279
u8 dev_xdp_prog_count(struct net_device *dev);
4280+
int netif_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);
42804281
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);
42814282
u8 dev_xdp_sb_prog_count(struct net_device *dev);
42824283
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode);

kernel/bpf/offload.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,10 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
528528
return ERR_PTR(-ENOMEM);
529529

530530
bpf_map_init_from_attr(&offmap->map, attr);
531-
532531
rtnl_lock();
533-
down_write(&bpf_devs_lock);
534532
offmap->netdev = __dev_get_by_index(net, attr->map_ifindex);
533+
netdev_lock_ops(offmap->netdev);
534+
down_write(&bpf_devs_lock);
535535
err = bpf_dev_offload_check(offmap->netdev);
536536
if (err)
537537
goto err_unlock;
@@ -548,12 +548,14 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
548548

549549
list_add_tail(&offmap->offloads, &ondev->maps);
550550
up_write(&bpf_devs_lock);
551+
netdev_unlock_ops(offmap->netdev);
551552
rtnl_unlock();
552553

553554
return &offmap->map;
554555

555556
err_unlock:
556557
up_write(&bpf_devs_lock);
558+
netdev_unlock_ops(offmap->netdev);
557559
rtnl_unlock();
558560
bpf_map_area_free(offmap);
559561
return ERR_PTR(err);

net/core/dev.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9852,7 +9852,7 @@ u8 dev_xdp_sb_prog_count(struct net_device *dev)
98529852
return count;
98539853
}
98549854

9855-
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
9855+
int netif_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
98569856
{
98579857
if (!dev->netdev_ops->ndo_bpf)
98589858
return -EOPNOTSUPP;
@@ -9872,7 +9872,6 @@ int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
98729872

98739873
return dev->netdev_ops->ndo_bpf(dev, bpf);
98749874
}
9875-
EXPORT_SYMBOL_GPL(dev_xdp_propagate);
98769875

98779876
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode)
98789877
{
@@ -9902,6 +9901,8 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
99029901
struct netdev_bpf xdp;
99039902
int err;
99049903

9904+
netdev_ops_assert_locked(dev);
9905+
99059906
if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
99069907
prog && !prog->aux->xdp_has_frags) {
99079908
NL_SET_ERR_MSG(extack, "unable to install XDP to device using tcp-data-split");
@@ -10134,7 +10135,9 @@ static void bpf_xdp_link_release(struct bpf_link *link)
1013410135
* already NULL, in which case link was already auto-detached
1013510136
*/
1013610137
if (xdp_link->dev) {
10138+
netdev_lock_ops(xdp_link->dev);
1013710139
WARN_ON(dev_xdp_detach_link(xdp_link->dev, NULL, xdp_link));
10140+
netdev_unlock_ops(xdp_link->dev);
1013810141
xdp_link->dev = NULL;
1013910142
}
1014010143

@@ -10216,10 +10219,12 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog,
1021610219
goto out_unlock;
1021710220
}
1021810221

10222+
netdev_lock_ops(xdp_link->dev);
1021910223
mode = dev_xdp_mode(xdp_link->dev, xdp_link->flags);
1022010224
bpf_op = dev_xdp_bpf_op(xdp_link->dev, mode);
1022110225
err = dev_xdp_install(xdp_link->dev, mode, bpf_op, NULL,
1022210226
xdp_link->flags, new_prog);
10227+
netdev_unlock_ops(xdp_link->dev);
1022310228
if (err)
1022410229
goto out_unlock;
1022510230

@@ -11005,7 +11010,9 @@ int register_netdevice(struct net_device *dev)
1100511010
if (ret)
1100611011
goto err_uninit_notify;
1100711012

11013+
netdev_lock_ops(dev);
1100811014
__netdev_update_features(dev);
11015+
netdev_unlock_ops(dev);
1100911016

1101011017
/*
1101111018
* Default initial state at registry is that the
@@ -11945,7 +11952,9 @@ void unregister_netdevice_many_notify(struct list_head *head,
1194511952
/* Shutdown queueing discipline. */
1194611953
dev_shutdown(dev);
1194711954
dev_tcx_uninstall(dev);
11955+
netdev_lock_ops(dev);
1194811956
dev_xdp_uninstall(dev);
11957+
netdev_unlock_ops(dev);
1194911958
bpf_dev_bound_netdev_unregister(dev);
1195011959
dev_memory_provider_uninstall(dev);
1195111960

net/core/dev_api.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,3 +317,15 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa,
317317
return ret;
318318
}
319319
EXPORT_SYMBOL(dev_set_mac_address);
320+
321+
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
322+
{
323+
int ret;
324+
325+
netdev_lock_ops(dev);
326+
ret = netif_xdp_propagate(dev, bpf);
327+
netdev_unlock_ops(dev);
328+
329+
return ret;
330+
}
331+
EXPORT_SYMBOL_GPL(dev_xdp_propagate);

net/xdp/xsk.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,8 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
11811181
goto out_release;
11821182
}
11831183

1184+
netdev_lock_ops(dev);
1185+
11841186
if (!xs->rx && !xs->tx) {
11851187
err = -EINVAL;
11861188
goto out_unlock;
@@ -1315,6 +1317,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
13151317
smp_wmb();
13161318
WRITE_ONCE(xs->state, XSK_BOUND);
13171319
}
1320+
netdev_unlock_ops(dev);
13181321
out_release:
13191322
mutex_unlock(&xs->mutex);
13201323
rtnl_unlock();

net/xdp/xsk_buff_pool.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3+
#include <linux/netdevice.h>
34
#include <net/xsk_buff_pool.h>
45
#include <net/xdp_sock.h>
56
#include <net/xdp_sock_drv.h>
@@ -219,6 +220,7 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
219220
bpf.xsk.pool = pool;
220221
bpf.xsk.queue_id = queue_id;
221222

223+
netdev_ops_assert_locked(netdev);
222224
err = netdev->netdev_ops->ndo_bpf(netdev, &bpf);
223225
if (err)
224226
goto err_unreg_pool;

0 commit comments

Comments
 (0)