]> git.baikalelectronics.ru Git - kernel.git/commit
block: fix use-after-free on gendisk
authorYufen Yu <yuyufen@huawei.com>
Tue, 2 Apr 2019 12:06:34 +0000 (20:06 +0800)
committerJens Axboe <axboe@kernel.dk>
Mon, 22 Apr 2019 15:48:12 +0000 (09:48 -0600)
commitcb35ad939731e3fbe773d9b5ce87a620441a32dc
tree2fb40867aa291075313719bd9bb5f8874c5bca96
parentb73a8d5677b99e1baaaf51f5182498077f4ed7e7
block: fix use-after-free on gendisk

commit 37376a2f265 "block: Fix dev_t minor allocation lifetime"
specifically moved blk_free_devt(dev->devt) call to part_release()
to avoid reallocating device number before the device is fully
shutdown.

However, it can cause use-after-free on gendisk in get_gendisk().
We use md device as example to show the race scenes:

Process1 Worker Process2
md_free
blkdev_open
del_gendisk
  add delete_partition_work_fn() to wq
   __blkdev_get
get_gendisk
put_disk
  disk_release
    kfree(disk)
     find part from ext_devt_idr
get_disk_and_module(disk)
        cause use after free

     delete_partition_work_fn
put_device(part)
        part_release
     remove part from ext_devt_idr

Before <devt, hd_struct pointer> is removed from ext_devt_idr by
delete_partition_work_fn(), we can find the devt and then access
gendisk by hd_struct pointer. But, if we access the gendisk after
it have been freed, it can cause in use-after-freeon gendisk in
get_gendisk().

We fix this by adding a new helper blk_invalidate_devt() in
delete_partition() and del_gendisk(). It replaces hd_struct
pointer in idr with value 'NULL', and deletes the entry from
idr in part_release() as we do now.

Thanks to Jan Kara for providing the solution and more clear comments
for the code.

Fixes: 37376a2f265c ("block: Fix dev_t minor allocation lifetime")
Cc: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Keith Busch <keith.busch@intel.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Yufen Yu <yuyufen@huawei.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/genhd.c
block/partition-generic.c
include/linux/genhd.h