• Xin Long's avatar
    vlan: move dev_put into vlan_dev_uninit · d6ff94af
    Xin Long authored
    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 563bcbae ("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().
    
    Fixes: 563bcbae ("net: vlan: fix a UAF in vlan_dev_real_dev()")
    Reported-by: default avatarShuang Li <shuali@redhat.com>
    Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    d6ff94af
vlan_dev.c 23.6 KB