• Coly Li's avatar
    bcache: fix refcount underflow in bcache_device_free() · 63581542
    Coly Li authored
    [ Upstream commit 86da9f73 ]
    
    The problematic code piece in bcache_device_free() is,
    
     785 static void bcache_device_free(struct bcache_device *d)
     786 {
     787     struct gendisk *disk = d->disk;
     [snipped]
     799     if (disk) {
     800             if (disk->flags & GENHD_FL_UP)
     801                     del_gendisk(disk);
     802
     803             if (disk->queue)
     804                     blk_cleanup_queue(disk->queue);
     805
     806             ida_simple_remove(&bcache_device_idx,
     807                               first_minor_to_idx(disk->first_minor));
     808             put_disk(disk);
     809         }
     [snipped]
     816 }
    
    At line 808, put_disk(disk) may encounter kobject refcount of 'disk'
    being underflow.
    
    Here is how to reproduce the issue,
    - Attche the backing device to a cache device and do random write to
      make the cache being dirty.
    - Stop the bcache device while the cache device has dirty data of the
      backing device.
    - Only register the backing device back, NOT register cache device.
    - The bcache device node /dev/bcache0 won't show up, because backing
      device waits for the cache device shows up for the missing dirty
      data.
    - Now echo 1 into /sys/fs/bcache/pendings_cleanup, to stop the pending
      backing device.
    - After the pending backing device stopped, use 'dmesg' to check kernel
      message, a use-after-free warning from KASA reported the refcount of
      kobject linked to the 'disk' is underflow.
    
    The dropping refcount at line 808 in the above code piece is added by
    add_disk(d->disk) in bch_cached_dev_run(). But in the above condition
    the cache device is not registered, bch_cached_dev_run() has no chance
    to be called and the refcount is not added. The put_disk() for a non-
    added refcount of gendisk kobject triggers a underflow warning.
    
    This patch checks whether GENHD_FL_UP is set in disk->flags, if it is
    not set then the bcache device was not added, don't call put_disk()
    and the the underflow issue can be avoided.
    Signed-off-by: default avatarColy Li <colyli@suse.de>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
    63581542
super.c 58.9 KB