__qdisc_destroy() calls into various qdiscs .destroy() op, which in turn
can call .ndo_setup_tc(), which requires the netdev instance lock.

This commit extends the critical section in
unregister_netdevice_many_notify() to cover dev_shutdown() (and
dev_tcx_uninstall() as a side-effect) and acquires the netdev instance
lock in __dev_change_net_namespace() for the other dev_shutdown() call.

This should now guarantee that for all qdisc ops, the netdev instance
lock is held during .ndo_setup_tc().

Fixes: a0527ee2df3f ("net: hold netdev instance lock during qdisc ndo_setup_tc")
Signed-off-by: Cosmin Ratiu <[email protected]>
---
 net/core/dev.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 1be7cb73a602..92e004c354ea 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11966,9 +11966,9 @@ void unregister_netdevice_many_notify(struct list_head 
*head,
                struct sk_buff *skb = NULL;
 
                /* Shutdown queueing discipline. */
+               netdev_lock_ops(dev);
                dev_shutdown(dev);
                dev_tcx_uninstall(dev);
-               netdev_lock_ops(dev);
                dev_xdp_uninstall(dev);
                dev_memory_provider_uninstall(dev);
                netdev_unlock_ops(dev);
@@ -12161,7 +12161,9 @@ int __dev_change_net_namespace(struct net_device *dev, 
struct net *net,
        synchronize_net();
 
        /* Shutdown queueing discipline. */
+       netdev_lock_ops(dev);
        dev_shutdown(dev);
+       netdev_unlock_ops(dev);
 
        /* Notify protocols, that we are about to destroy
         * this device. They should clean all the things.
-- 
2.45.0


Reply via email to