Skip to content

Commit 01d9cc2

Browse files
Ziyang Xuankuba-moo
authored andcommitted
net: vlan: fix underflow for the real_dev refcnt
Inject error before dev_hold(real_dev) in register_vlan_dev(), and execute the following testcase: ip link add dev dummy1 type dummy ip link add name dummy1.100 link dummy1 type vlan id 100 ip link del dev dummy1 When the dummy netdevice is removed, we will get a WARNING as following: ======================================================================= refcount_t: decrement hit 0; leaking memory. WARNING: CPU: 2 PID: 0 at lib/refcount.c:31 refcount_warn_saturate+0xbf/0x1e0 and an endless loop of: ======================================================================= unregister_netdevice: waiting for dummy1 to become free. Usage count = -1073741824 That is because dev_put(real_dev) in vlan_dev_free() be called without dev_hold(real_dev) in register_vlan_dev(). It makes the refcnt of real_dev underflow. Move the dev_hold(real_dev) to vlan_dev_init() which is the call-back of ndo_init(). That makes dev_hold() and dev_put() for vlan's real_dev symmetrical. Fixes: 563bcba ("net: vlan: fix a UAF in vlan_dev_real_dev()") Reported-by: Petr Machata <[email protected]> Suggested-by: Jakub Kicinski <[email protected]> Signed-off-by: Ziyang Xuan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent cbb91dc commit 01d9cc2

File tree

2 files changed

+3
-3
lines changed

2 files changed

+3
-3
lines changed

net/8021q/vlan.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,6 @@ int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack)
184184
if (err)
185185
goto out_unregister_netdev;
186186

187-
/* Account for reference in struct vlan_dev_priv */
188-
dev_hold(real_dev);
189-
190187
vlan_stacked_transfer_operstate(real_dev, dev, vlan);
191188
linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
192189

net/8021q/vlan_dev.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ static int vlan_dev_init(struct net_device *dev)
615615
if (!vlan->vlan_pcpu_stats)
616616
return -ENOMEM;
617617

618+
/* Get vlan's reference to real_dev */
619+
dev_hold(real_dev);
620+
618621
return 0;
619622
}
620623

0 commit comments

Comments
 (0)