mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
net: hold netdev instance lock during ndo_bpf
Cover the paths that come via bpf system call and XSK bind. Cc: Saeed Mahameed <saeed@kernel.org> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20250305163732.2766420-10-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
ad7c7b2172
commit
97246d6d21
6 changed files with 33 additions and 4 deletions
|
@ -4277,6 +4277,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
|||
|
||||
int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
|
||||
u8 dev_xdp_prog_count(struct net_device *dev);
|
||||
int netif_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);
|
||||
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);
|
||||
u8 dev_xdp_sb_prog_count(struct net_device *dev);
|
||||
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode);
|
||||
|
|
|
@ -528,10 +528,10 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
bpf_map_init_from_attr(&offmap->map, attr);
|
||||
|
||||
rtnl_lock();
|
||||
down_write(&bpf_devs_lock);
|
||||
offmap->netdev = __dev_get_by_index(net, attr->map_ifindex);
|
||||
netdev_lock_ops(offmap->netdev);
|
||||
down_write(&bpf_devs_lock);
|
||||
err = bpf_dev_offload_check(offmap->netdev);
|
||||
if (err)
|
||||
goto err_unlock;
|
||||
|
@ -548,12 +548,14 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
|
|||
|
||||
list_add_tail(&offmap->offloads, &ondev->maps);
|
||||
up_write(&bpf_devs_lock);
|
||||
netdev_unlock_ops(offmap->netdev);
|
||||
rtnl_unlock();
|
||||
|
||||
return &offmap->map;
|
||||
|
||||
err_unlock:
|
||||
up_write(&bpf_devs_lock);
|
||||
netdev_unlock_ops(offmap->netdev);
|
||||
rtnl_unlock();
|
||||
bpf_map_area_free(offmap);
|
||||
return ERR_PTR(err);
|
||||
|
|
|
@ -9852,7 +9852,7 @@ u8 dev_xdp_sb_prog_count(struct net_device *dev)
|
|||
return count;
|
||||
}
|
||||
|
||||
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
|
||||
int netif_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
|
||||
{
|
||||
if (!dev->netdev_ops->ndo_bpf)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -9872,7 +9872,6 @@ int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
|
|||
|
||||
return dev->netdev_ops->ndo_bpf(dev, bpf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_xdp_propagate);
|
||||
|
||||
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode)
|
||||
{
|
||||
|
@ -9902,6 +9901,8 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
|
|||
struct netdev_bpf xdp;
|
||||
int err;
|
||||
|
||||
netdev_ops_assert_locked(dev);
|
||||
|
||||
if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
prog && !prog->aux->xdp_has_frags) {
|
||||
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)
|
|||
* already NULL, in which case link was already auto-detached
|
||||
*/
|
||||
if (xdp_link->dev) {
|
||||
netdev_lock_ops(xdp_link->dev);
|
||||
WARN_ON(dev_xdp_detach_link(xdp_link->dev, NULL, xdp_link));
|
||||
netdev_unlock_ops(xdp_link->dev);
|
||||
xdp_link->dev = NULL;
|
||||
}
|
||||
|
||||
|
@ -10216,10 +10219,12 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
netdev_lock_ops(xdp_link->dev);
|
||||
mode = dev_xdp_mode(xdp_link->dev, xdp_link->flags);
|
||||
bpf_op = dev_xdp_bpf_op(xdp_link->dev, mode);
|
||||
err = dev_xdp_install(xdp_link->dev, mode, bpf_op, NULL,
|
||||
xdp_link->flags, new_prog);
|
||||
netdev_unlock_ops(xdp_link->dev);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
|
@ -11005,7 +11010,9 @@ int register_netdevice(struct net_device *dev)
|
|||
if (ret)
|
||||
goto err_uninit_notify;
|
||||
|
||||
netdev_lock_ops(dev);
|
||||
__netdev_update_features(dev);
|
||||
netdev_unlock_ops(dev);
|
||||
|
||||
/*
|
||||
* Default initial state at registry is that the
|
||||
|
@ -11945,7 +11952,9 @@ void unregister_netdevice_many_notify(struct list_head *head,
|
|||
/* Shutdown queueing discipline. */
|
||||
dev_shutdown(dev);
|
||||
dev_tcx_uninstall(dev);
|
||||
netdev_lock_ops(dev);
|
||||
dev_xdp_uninstall(dev);
|
||||
netdev_unlock_ops(dev);
|
||||
bpf_dev_bound_netdev_unregister(dev);
|
||||
dev_memory_provider_uninstall(dev);
|
||||
|
||||
|
|
|
@ -317,3 +317,15 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa,
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dev_set_mac_address);
|
||||
|
||||
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
netdev_lock_ops(dev);
|
||||
ret = netif_xdp_propagate(dev, bpf);
|
||||
netdev_unlock_ops(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_xdp_propagate);
|
||||
|
|
|
@ -1181,6 +1181,8 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
|
|||
goto out_release;
|
||||
}
|
||||
|
||||
netdev_lock_ops(dev);
|
||||
|
||||
if (!xs->rx && !xs->tx) {
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
|
@ -1315,6 +1317,7 @@ out_unlock:
|
|||
smp_wmb();
|
||||
WRITE_ONCE(xs->state, XSK_BOUND);
|
||||
}
|
||||
netdev_unlock_ops(dev);
|
||||
out_release:
|
||||
mutex_unlock(&xs->mutex);
|
||||
rtnl_unlock();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/xsk_buff_pool.h>
|
||||
#include <net/xdp_sock.h>
|
||||
#include <net/xdp_sock_drv.h>
|
||||
|
@ -219,6 +220,7 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
|
|||
bpf.xsk.pool = pool;
|
||||
bpf.xsk.queue_id = queue_id;
|
||||
|
||||
netdev_ops_assert_locked(netdev);
|
||||
err = netdev->netdev_ops->ndo_bpf(netdev, &bpf);
|
||||
if (err)
|
||||
goto err_unreg_pool;
|
||||
|
|
Loading…
Add table
Reference in a new issue