FAILED: patch "[PATCH] vlan: move dev_put into vlan_dev_uninit" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d6ff94afd90b0ce8d1715f8ef77d4347d7a7f2c0 Mon Sep 17 00:00:00 2001
From: Xin Long <[email protected]>
Date: Wed, 9 Feb 2022 03:19:56 -0500
Subject: [PATCH] vlan: move dev_put into vlan_dev_uninit
Shuang Li reported an QinQ issue by simply doing:
# ip link add dummy0 type dummy # ip link add link dummy0 name dummy0.1 type vlan id 1 # ip link add link dummy0.1 name dummy0.1.2 type vlan id 2 # rmmod 8021q
unregister_netdevice: waiting for dummy0.1 to become free. Usage count = 1
When rmmods 8021q, all vlan devs are deleted from their real_dev's vlan grp and added into list_kill by unregister_vlan_dev(). dummy0.1 is unregistered before dummy0.1.2, as it's using for_each_netdev() in __rtnl_kill_links().
When unregisters dummy0.1, dummy0.1.2 is not unregistered in the event of NETDEV_UNREGISTER, as it's been deleted from dummy0.1's vlan grp. However, due to dummy0.1.2 still holding dummy0.1, dummy0.1 will keep waiting in netdev_wait_allrefs(), while dummy0.1.2 will never get unregistered and release dummy0.1, as it delays dev_put until calling dev->priv_destructor, vlan_dev_free().
This issue was introduced by Commit 563bcbae3ba2 ("net: vlan: fix a UAF in vlan_dev_real_dev()"), and this patch is to fix it by moving dev_put() into vlan_dev_uninit(), which is called after NETDEV_UNREGISTER event but before netdev_wait_allrefs().
net/8021q/vlan_dev.c +5 -3
@@ -638,7 +638,12 @@ void vlan_dev_free_egress_priority(const struct net_device *dev)static void vlan_dev_uninit (struct net_device *dev) { +struct vlan_dev_priv *vlan =vlan_dev_priv (dev); +vlan_dev_free_egress_priority (dev); + +/* Get rid of the vlan's reference to real_dev */ +dev_put_track (vlan->real_dev, &vlan->dev_tracker); } static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
@@ -851,9 +856,6 @@ static void vlan_dev_free(struct net_device *dev)free_percpu (vlan->vlan_pcpu_stats); vlan->vlan_pcpu_stats =NULL ; - -/* Get rid of the vlan's reference to real_dev */ -dev_put_track (vlan->real_dev, &vlan->dev_tracker); }void vlan_setup (struct net_device *dev)