• Eric Dumazet's avatar
    tun: handle register_netdevice() failures properly · dda84477
    Eric Dumazet authored
    
    [ Upstream commit ff244c6b ]
    
    syzkaller reported a double free [1], caused by the fact
    that tun driver was not updated properly when priv_destructor
    was added.
    
    When/if register_netdevice() fails, priv_destructor() must have been
    called already.
    
    [1]
    BUG: KASAN: double-free or invalid-free in selinux_tun_dev_free_security+0x15/0x20 security/selinux/hooks.c:5023
    
    CPU: 0 PID: 2919 Comm: syzkaller227220 Not tainted 4.13.0-rc4+ #23
    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
    Call Trace:
     __dump_stack lib/dump_stack.c:16 [inline]
     dump_stack+0x194/0x257 lib/dump_stack.c:52
     print_address_description+0x7f/0x260 mm/kasan/report.c:252
     kasan_report_double_free+0x55/0x80 mm/kasan/report.c:333
     kasan_slab_free+0xa0/0xc0 mm/kasan/kasan.c:514
     __cache_free mm/slab.c:3503 [inline]
     kfree+0xd3/0x260 mm/slab.c:3820
     selinux_tun_dev_free_security+0x15/0x20 security/selinux/hooks.c:5023
     security_tun_dev_free_security+0x48/0x80 security/security.c:1512
     tun_set_iff drivers/net/tun.c:1884 [inline]
     __tun_chr_ioctl+0x2ce6/0x3d50 drivers/net/tun.c:2064
     tun_chr_ioctl+0x2a/0x40 drivers/net/tun.c:2309
     vfs_ioctl fs/ioctl.c:45 [inline]
     do_vfs_ioctl+0x1b1/0x1520 fs/ioctl.c:685
     SYSC_ioctl fs/ioctl.c:700 [inline]
     SyS_ioctl+0x8f/0xc0 fs/ioctl.c:691
     entry_SYSCALL_64_fastpath+0x1f/0xbe
    RIP: 0033:0x443ff9
    RSP: 002b:00007ffc34271f68 EFLAGS: 00000217 ORIG_RAX: 0000000000000010
    RAX: ffffffffffffffda RBX: 00000000004002e0 RCX: 0000000000443ff9
    RDX: 0000000020533000 RSI: 00000000400454ca RDI: 0000000000000003
    RBP: 0000000000000086 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000000 R11: 0000000000000217 R12: 0000000000401ce0
    R13: 0000000000401d70 R14: 0000000000000000 R15: 0000000000000000
    
    Allocated by task 2919:
     save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
     save_stack+0x43/0xd0 mm/kasan/kasan.c:447
     set_track mm/kasan/kasan.c:459 [inline]
     kasan_kmalloc+0xaa/0xd0 mm/kasan/kasan.c:551
     kmem_cache_alloc_trace+0x101/0x6f0 mm/slab.c:3627
     kmalloc include/linux/slab.h:493 [inline]
     kzalloc include/linux/slab.h:666 [inline]
     selinux_tun_dev_alloc_security+0x49/0x170 security/selinux/hooks.c:5012
     security_tun_dev_alloc_security+0x6d/0xa0 security/security.c:1506
     tun_set_iff drivers/net/tun.c:1839 [inline]
     __tun_chr_ioctl+0x1730/0x3d50 drivers/net/tun.c:2064
     tun_chr_ioctl+0x2a/0x40 drivers/net/tun.c:2309
     vfs_ioctl fs/ioctl.c:45 [inline]
     do_vfs_ioctl+0x1b1/0x1520 fs/ioctl.c:685
     SYSC_ioctl fs/ioctl.c:700 [inline]
     SyS_ioctl+0x8f/0xc0 fs/ioctl.c:691
     entry_SYSCALL_64_fastpath+0x1f/0xbe
    
    Freed by task 2919:
     save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
     save_stack+0x43/0xd0 mm/kasan/kasan.c:447
     set_track mm/kasan/kasan.c:459 [inline]
     kasan_slab_free+0x6e/0xc0 mm/kasan/kasan.c:524
     __cache_free mm/slab.c:3503 [inline]
     kfree+0xd3/0x260 mm/slab.c:3820
     selinux_tun_dev_free_security+0x15/0x20 security/selinux/hooks.c:5023
     security_tun_dev_free_security+0x48/0x80 security/security.c:1512
     tun_free_netdev+0x13b/0x1b0 drivers/net/tun.c:1563
     register_netdevice+0x8d0/0xee0 net/core/dev.c:7605
     tun_set_iff drivers/net/tun.c:1859 [inline]
     __tun_chr_ioctl+0x1caf/0x3d50 drivers/net/tun.c:2064
     tun_chr_ioctl+0x2a/0x40 drivers/net/tun.c:2309
     vfs_ioctl fs/ioctl.c:45 [inline]
     do_vfs_ioctl+0x1b1/0x1520 fs/ioctl.c:685
     SYSC_ioctl fs/ioctl.c:700 [inline]
     SyS_ioctl+0x8f/0xc0 fs/ioctl.c:691
     entry_SYSCALL_64_fastpath+0x1f/0xbe
    
    The buggy address belongs to the object at ffff8801d2843b40
     which belongs to the cache kmalloc-32 of size 32
    The buggy address is located 0 bytes inside of
     32-byte region [ffff8801d2843b40, ffff8801d2843b60)
    The buggy address belongs to the page:
    page:ffffea000660cea8 count:1 mapcount:0 mapping:ffff8801d2843000 index:0xffff8801d2843fc1
    flags: 0x200000000000100(slab)
    raw: 0200000000000100 ffff8801d2843000 ffff8801d2843fc1 000000010000003f
    raw: ffffea0006626a40 ffffea00066141a0 ffff8801dbc00100
    page dumped because: kasan: bad access detected
    
    Memory state around the buggy address:
     ffff8801d2843a00: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
     ffff8801d2843a80: 00 00 00 fc fc fc fc fc fb fb fb fb fc fc fc fc
    >ffff8801d2843b00: 00 00 00 00 fc fc fc fc fb fb fb fb fc fc fc fc
                                               ^
     ffff8801d2843b80: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
     ffff8801d2843c00: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
    
    ==================================================================
    
    Fixes: cf124db5 ("net: Fix inconsistent teardown and release of private netdev state.")
    Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    dda84477
tun.c 61 KB