summaryrefslogtreecommitdiffstats
path: root/block/genhd.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2018-02-26 13:01:40 +0100
committerJens Axboe <axboe@kernel.dk>2018-02-26 09:48:42 -0700
commit897366537fb65e87755b822360c230354c3fc73b (patch)
tree6e5106b9b1d9aacdd0e12e560a8cc8021d4cb1e6 /block/genhd.c
parent9df6c29912315186fef1c79cc15b758ace84175b (diff)
downloadlinux-0-day-897366537fb65e87755b822360c230354c3fc73b.tar.gz
linux-0-day-897366537fb65e87755b822360c230354c3fc73b.tar.xz
genhd: Fix use after free in __blkdev_get()
When two blkdev_open() calls race with device removal and recreation, __blkdev_get() can use looked up gendisk after it is freed: CPU0 CPU1 CPU2 del_gendisk(disk); bdev_unhash_inode(inode); blkdev_open() blkdev_open() bdev = bd_acquire(inode); - creates and returns new inode bdev = bd_acquire(inode); - returns the same inode __blkdev_get(devt) __blkdev_get(devt) disk = get_gendisk(devt); - got structure of device going away <finish device removal> <new device gets created under the same device number> disk = get_gendisk(devt); - got new device structure if (!bdev->bd_openers) { does the first open } if (!bdev->bd_openers) - false } else { put_disk_and_module(disk) - remember this was old device - this was last ref and disk is now freed } disk_unblock_events(disk); -> oops Fix the problem by making sure we drop reference to disk in __blkdev_get() only after we are really done with it. Reported-by: Hou Tao <houtao1@huawei.com> Tested-by: Hou Tao <houtao1@huawei.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/genhd.c')
0 files changed, 0 insertions, 0 deletions