• Vincent Whitchurch's avatar
    mic: vop: Fix use-after-free on remove · 1ce0fceb
    Vincent Whitchurch authored
    commit 70ed7148 upstream.
    
    KASAN detects a use-after-free when vop devices are removed.
    
    This problem was introduced by commit 0063e8bb ("virtio_vop:
    don't kfree device on register failure").  That patch moved the freeing
    of the struct _vop_vdev to the release function, but failed to ensure
    that vop holds a reference to the device when it doesn't want it to go
    away.  A kfree() was replaced with a put_device() in the unregistration
    path, but the last reference to the device is already dropped in
    unregister_virtio_device() so the struct is freed before vop is done
    with it.
    
    Fix it by holding a reference until cleanup is done.  This is similar to
    the fix in virtio_pci in commit 2989be09 ("virtio_pci: fix use
    after free on release").
    
     ==================================================================
     BUG: KASAN: use-after-free in vop_scan_devices+0xc6c/0xe50 [vop]
     Read of size 8 at addr ffff88800da18580 by task kworker/0:1/12
    
     CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.0.0-rc4+ #53
     Workqueue: events vop_hotplug_devices [vop]
     Call Trace:
      dump_stack+0x74/0xbb
      print_address_description+0x5d/0x2b0
      ? vop_scan_devices+0xc6c/0xe50 [vop]
      kasan_report+0x152/0x1aa
      ? vop_scan_devices+0xc6c/0xe50 [vop]
      ? vop_scan_devices+0xc6c/0xe50 [vop]
      vop_scan_devices+0xc6c/0xe50 [vop]
      ? vop_loopback_free_irq+0x160/0x160 [vop_loopback]
      process_one_work+0x7c0/0x14b0
      ? pwq_dec_nr_in_flight+0x2d0/0x2d0
      ? do_raw_spin_lock+0x120/0x280
      worker_thread+0x8f/0xbf0
      ? __kthread_parkme+0x78/0xf0
      ? process_one_work+0x14b0/0x14b0
      kthread+0x2ae/0x3a0
      ? kthread_park+0x120/0x120
      ret_from_fork+0x3a/0x50
    
     Allocated by task 12:
      kmem_cache_alloc_trace+0x13a/0x2a0
      vop_scan_devices+0x473/0xe50 [vop]
      process_one_work+0x7c0/0x14b0
      worker_thread+0x8f/0xbf0
      kthread+0x2ae/0x3a0
      ret_from_fork+0x3a/0x50
    
     Freed by task 12:
      kfree+0x104/0x310
      device_release+0x73/0x1d0
      kobject_put+0x14f/0x420
      unregister_virtio_device+0x32/0x50
      vop_scan_devices+0x19d/0xe50 [vop]
      process_one_work+0x7c0/0x14b0
      worker_thread+0x8f/0xbf0
      kthread+0x2ae/0x3a0
      ret_from_fork+0x3a/0x50
    
     The buggy address belongs to the object at ffff88800da18008
      which belongs to the cache kmalloc-2k of size 2048
     The buggy address is located 1400 bytes inside of
      2048-byte region [ffff88800da18008, ffff88800da18808)
     The buggy address belongs to the page:
     page:ffffea0000368600 count:1 mapcount:0 mapping:ffff88801440dbc0 index:0x0 compound_mapcount: 0
     flags: 0x4000000000010200(slab|head)
     raw: 4000000000010200 ffffea0000378608 ffffea000037a008 ffff88801440dbc0
     raw: 0000000000000000 00000000000d000d 00000001ffffffff 0000000000000000
     page dumped because: kasan: bad access detected
    
     Memory state around the buggy address:
      ffff88800da18480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      ffff88800da18500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     >ffff88800da18580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                        ^
      ffff88800da18600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      ffff88800da18680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ==================================================================
    
    Fixes: 0063e8bb ("virtio_vop: don't kfree device on register failure")
    Signed-off-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
    Cc: stable <stable@vger.kernel.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    1ce0fceb
vop_main.c 20 KB