hulk inclusion category: bugfix bugzilla: 189153, https://gitee.com/openeuler/kernel/issues/I7XVQD CVE: NA
----------------------------------------
Creating and using dm device at same time may trigger null-ptr-deref or deadlock. Some resources have not been initialized after calling add_disk in the process of creating dm device, which means users can get device and use some uninitialized resources. Using uninitialized resources may trigger null-ptr-deref directly. What's more, IO can't be finished by waiting specific resources to be initialized and the resources can't be initialized since IO is inflight, which triggers deadlock.
Don't get gendisk if queue has not been registered to fix this.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- block/blk-sysfs.c | 4 ++-- block/blk-throttle.c | 2 +- fs/block_dev.c | 6 ++++++ include/linux/blkdev.h | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index db7c0503bead..c95be9626a09 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -908,7 +908,7 @@ int blk_register_queue(struct gendisk *disk) wbt_enable_default(q); blk_throtl_register_queue(q); spin_lock_irq(&q->queue_lock); - blk_queue_flag_set(QUEUE_FLAG_THROTL_INIT_DONE, q); + blk_queue_flag_set(QUEUE_FLAG_REGISTER_DONE, q); spin_unlock_irq(&q->queue_lock);
/* Now everything is ready and send out KOBJ_ADD uevent */ @@ -944,7 +944,7 @@ void blk_unregister_queue(struct gendisk *disk) return;
spin_lock_irq(&q->queue_lock); - blk_queue_flag_clear(QUEUE_FLAG_THROTL_INIT_DONE, q); + blk_queue_flag_clear(QUEUE_FLAG_REGISTER_DONE, q); spin_unlock_irq(&q->queue_lock);
/* diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 2686634d2cc4..42ce18f991c4 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1518,7 +1518,7 @@ static void tg_conf_updated(struct throtl_grp *tg, u64 *old_limits, bool global)
static inline int throtl_check_init_done(struct request_queue *q) { - if (test_bit(QUEUE_FLAG_THROTL_INIT_DONE, &q->queue_flags)) + if (test_bit(QUEUE_FLAG_REGISTER_DONE, &q->queue_flags)) return 0;
return blk_queue_dying(q) ? -ENODEV : -EBUSY; diff --git a/fs/block_dev.c b/fs/block_dev.c index 1c56cddcaa3d..a0e4d3ec300e 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1136,6 +1136,12 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
if (!disk) return NULL; + + if (!test_bit(QUEUE_FLAG_REGISTER_DONE, &disk->queue->queue_flags)) { + put_disk_and_module(disk); + return NULL; + } + /* * Now that we hold gendisk reference we make sure bdev we looked up is * not stale. If it is, it means device got removed and created before diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9ede0a81e466..93f1a7586f86 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -612,7 +612,7 @@ struct request_queue { /* Keep blk_queue_flag_name[] in sync with the definitions below */ #define QUEUE_FLAG_STOPPED 0 /* queue is stopped */ #define QUEUE_FLAG_DYING 1 /* queue being torn down */ -#define QUEUE_FLAG_THROTL_INIT_DONE 2 /* io throttle can be online */ +#define QUEUE_FLAG_REGISTER_DONE 2 /* blkdev can be got */ #define QUEUE_FLAG_NOMERGES 3 /* disable merge attempts */ #define QUEUE_FLAG_SAME_COMP 4 /* complete on same CPU-group */ #define QUEUE_FLAG_FAIL_IO 5 /* fake timeout */