Skip to content

Commit 3ec5233

Browse files
Saurabh Sengarkuba-moo
Saurabh Sengar
authored andcommitted
hv_netvsc: fix potential deadlock in netvsc_vf_setxdp()
The MANA driver's probe registers netdevice via the following call chain: mana_probe() register_netdev() register_netdevice() register_netdevice() calls notifier callback for netvsc driver, holding the netdev mutex via netdev_lock_ops(). Further this netvsc notifier callback end up attempting to acquire the same lock again in dev_xdp_propagate() leading to deadlock. netvsc_netdev_event() netvsc_vf_setxdp() dev_xdp_propagate() This deadlock was not observed so far because net_shaper_ops was never set, and thus the lock was effectively a no-op in this case. Fix this by using netif_xdp_propagate() instead of dev_xdp_propagate() to avoid recursive locking in this path. And, since no deadlock is observed on the other path which is via netvsc_probe, add the lock exclusivly for that path. Also, clean up the unregistration path by removing the unnecessary call to netvsc_vf_setxdp(), since unregister_netdevice_many_notify() already performs this cleanup via dev_xdp_uninstall(). Fixes: 97246d6 ("net: hold netdev instance lock during ndo_bpf") Cc: [email protected] Signed-off-by: Saurabh Sengar <[email protected]> Tested-by: Erni Sri Satya Vennela <[email protected]> Reviewed-by: Haiyang Zhang <[email protected]> Reviewed-by: Subbaraya Sundeep <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent c1f4cb8 commit 3ec5233

File tree

3 files changed

+4
-3
lines changed

3 files changed

+4
-3
lines changed

drivers/net/hyperv/netvsc_bpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ int netvsc_vf_setxdp(struct net_device *vf_netdev, struct bpf_prog *prog)
183183
xdp.command = XDP_SETUP_PROG;
184184
xdp.prog = prog;
185185

186-
ret = dev_xdp_propagate(vf_netdev, &xdp);
186+
ret = netif_xdp_propagate(vf_netdev, &xdp);
187187

188188
if (ret && prog)
189189
bpf_prog_put(prog);

drivers/net/hyperv/netvsc_drv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,8 +2462,6 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
24622462

24632463
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
24642464

2465-
netvsc_vf_setxdp(vf_netdev, NULL);
2466-
24672465
reinit_completion(&net_device_ctx->vf_add);
24682466
netdev_rx_handler_unregister(vf_netdev);
24692467
netdev_upper_dev_unlink(vf_netdev, ndev);
@@ -2631,7 +2629,9 @@ static int netvsc_probe(struct hv_device *dev,
26312629
continue;
26322630

26332631
netvsc_prepare_bonding(vf_netdev);
2632+
netdev_lock_ops(vf_netdev);
26342633
netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE);
2634+
netdev_unlock_ops(vf_netdev);
26352635
__netvsc_vf_setup(net, vf_netdev);
26362636
break;
26372637
}

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9968,6 +9968,7 @@ int netif_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
99689968

99699969
return dev->netdev_ops->ndo_bpf(dev, bpf);
99709970
}
9971+
EXPORT_SYMBOL_GPL(netif_xdp_propagate);
99719972

99729973
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode)
99739974
{

0 commit comments

Comments
 (0)