Unverified Commit a0201f3d authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3253 Add error handle for driver

Merge Pull Request from: @ci-robot 
 
PR sync from: Li Nan <linan122@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2C5TD2RMCAFLI6BTOG4CHWQZULYSDUV3/ 
And revert redundant patches of nbd to resolve conflict.

Christoph Hellwig (9):
  block: add blk_alloc_disk and blk_cleanup_disk APIs
  blk-mq: add the blk_mq_alloc_disk APIs
  loop: use blk_mq_alloc_disk and blk_cleanup_disk
  loop: fix order of cleaning up the queue and freeing the tagset
  nbd: use blk_mq_alloc_disk and blk_cleanup_disk
  block: add a flag to make put_disk on partially initalized disks safer
  nvme: use blk_mq_alloc_disk
  brd: convert to blk_alloc_disk/blk_cleanup_disk
  ubi: use blk_mq_alloc_disk and blk_cleanup_disk

Dan Carpenter (1):
  blk-mq: fix an IS_ERR() vs NULL bug

Li Lingfeng (1):
  nbd: fix uaf in nbd_open

Li Nan (1):
  nbd: Revert redundant patches of nbd first_minor

Luis Chamberlain (7):
  loop: add error handling support for add_disk()
  nbd: add error handling support for add_disk()
  nvme: add error handling support for add_disk()
  block/brd: add error handling support for add_disk()
  scsi: sd: Add error handling support for add_disk()
  scsi: sr: Add error handling support for add_disk()
  mtd/ubi/block: add error handling support for add_disk()

Wang Qing (1):
  nbd: fix order of cleaning up the queue and freeing the tagset

Zhong Jinghua (3):
  scsi: sd: Clean up sdkp if device_add_disk() failed
  mtd/ubi/block: Fix null pointer dereference issue in error path
  mtd/ubi/block: Fix uaf problem in ubiblock_cleanup


-- 
2.39.2
 
https://gitee.com/openeuler/kernel/issues/I81XCK 
 
Link:https://gitee.com/openeuler/kernel/pulls/3253

 

Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 1b220dec 59775736
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -3310,6 +3310,25 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
}
EXPORT_SYMBOL(blk_mq_init_queue);

struct gendisk *__blk_mq_alloc_disk(struct blk_mq_tag_set *set, void *queuedata)
{
	struct request_queue *q;
	struct gendisk *disk;

	q = blk_mq_init_queue_data(set, queuedata);
	if (IS_ERR(q))
		return ERR_CAST(q);

	disk = __alloc_disk_node(0, set->numa_node);
	if (!disk) {
		blk_cleanup_queue(q);
		return ERR_PTR(-ENOMEM);
	}
	disk->queue = q;
	return disk;
}
EXPORT_SYMBOL(__blk_mq_alloc_disk);

/*
 * Helper for setting up a queue with mq ops, given queue depth, and
 * the passed in mq ops flags.
+40 −2
Original line number Diff line number Diff line
@@ -781,7 +781,10 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk,
	 * Take an extra ref on queue which will be put on disk_release()
	 * so that it sticks around as long as @disk is there.
	 */
	WARN_ON_ONCE(!blk_get_queue(disk->queue));
	if (blk_get_queue(disk->queue))
		set_bit(GD_QUEUE_REF, &disk->state);
	else
		WARN_ON_ONCE(1);
	/*
	 * The disk queue should now be all set with enough information about
	 * the device for the elevator code to pick an adequate default
@@ -1725,7 +1728,7 @@ static void disk_release(struct device *dev)
	kfree(disk->random);
	disk_replace_part_tbl(disk, NULL);
	hd_free_part(&disk->part0);
	if (disk->queue)
	if (test_bit(GD_QUEUE_REF, &disk->state) && disk->queue)
		blk_put_queue(disk->queue);
	kfree(disk);
}
@@ -1927,6 +1930,25 @@ struct gendisk *__alloc_disk_node(int minors, int node_id)
}
EXPORT_SYMBOL(__alloc_disk_node);

struct gendisk *__blk_alloc_disk(int node)
{
	struct request_queue *q;
	struct gendisk *disk;

	q = blk_alloc_queue(node);
	if (!q)
		return NULL;

	disk = __alloc_disk_node(0, node);
	if (!disk) {
		blk_cleanup_queue(q);
		return NULL;
	}
	disk->queue = q;
	return disk;
}
EXPORT_SYMBOL(__blk_alloc_disk);

/**
 * get_disk_and_module - increments the gendisk and gendisk fops module refcount
 * @disk: the struct gendisk to increment the refcount for
@@ -1973,6 +1995,22 @@ void put_disk(struct gendisk *disk)
}
EXPORT_SYMBOL(put_disk);

/**
 * blk_cleanup_disk - shutdown a gendisk allocated by blk_alloc_disk
 * @disk: gendisk to shutdown
 *
 * Mark the queue hanging off @disk DYING, drain all pending requests, then mark
 * the queue DEAD, destroy and put it and the gendisk structure.
 *
 * Context: can sleep
 */
void blk_cleanup_disk(struct gendisk *disk)
{
	blk_cleanup_queue(disk->queue);
	put_disk(disk);
}
EXPORT_SYMBOL(blk_cleanup_disk);

/**
 * put_disk_and_module - decrements the module and gendisk refcount
 * @disk: the struct gendisk to decrement the refcount for
+44 −59
Original line number Diff line number Diff line
@@ -38,8 +38,6 @@
 */
struct brd_device {
	int			brd_number;

	struct request_queue	*brd_queue;
	struct gendisk		*brd_disk;
	struct list_head	brd_list;

@@ -373,71 +371,68 @@ static LIST_HEAD(brd_devices);
static DEFINE_MUTEX(brd_devices_mutex);
static struct dentry *brd_debugfs_dir;

static struct brd_device *brd_alloc(int i)
static int brd_alloc(int i)
{
	struct brd_device *brd;
	struct gendisk *disk;
	char buf[DISK_NAME_LEN];
	int err = -ENOMEM;

	brd = kzalloc(sizeof(*brd), GFP_KERNEL);
	if (!brd)
		goto out;
		return -ENOMEM;
	brd->brd_number		= i;
	spin_lock_init(&brd->brd_lock);
	INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC);

	brd->brd_queue = blk_alloc_queue(NUMA_NO_NODE);
	if (!brd->brd_queue)
		goto out_free_dev;

	snprintf(buf, DISK_NAME_LEN, "ram%d", i);
	if (!IS_ERR_OR_NULL(brd_debugfs_dir))
		debugfs_create_u64(buf, 0444, brd_debugfs_dir,
				&brd->brd_nr_pages);

	/* This is so fdisk will align partitions on 4k, because of
	 * direct_access API needing 4k alignment, returning a PFN
	 * (This is only a problem on very small devices <= 4M,
	 *  otherwise fdisk will align on 1M. Regardless this call
	 *  is harmless)
	 */
	blk_queue_physical_block_size(brd->brd_queue, PAGE_SIZE);
	disk = brd->brd_disk = alloc_disk(max_part);
	disk = brd->brd_disk = blk_alloc_disk(NUMA_NO_NODE);
	if (!disk)
		goto out_free_queue;
		goto out_free_dev;

	disk->major		= RAMDISK_MAJOR;
	disk->first_minor	= i * max_part;
	disk->minors		= max_part;
	disk->fops		= &brd_fops;
	disk->private_data	= brd;
	disk->flags		= GENHD_FL_EXT_DEVT;
	strlcpy(disk->disk_name, buf, DISK_NAME_LEN);
	set_capacity(disk, rd_size * 2);
	
	/*
	 * This is so fdisk will align partitions on 4k, because of
	 * direct_access API needing 4k alignment, returning a PFN
	 * (This is only a problem on very small devices <= 4M,
	 *  otherwise fdisk will align on 1M. Regardless this call
	 *  is harmless)
	 */
	blk_queue_physical_block_size(disk->queue, PAGE_SIZE);

	/* Tell the block layer that this is not a rotational device */
	blk_queue_flag_set(QUEUE_FLAG_NONROT, brd->brd_queue);
	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, brd->brd_queue);
	blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
	err = add_disk_safe(disk);
	if (err)
		goto out_cleanup_disk;
	list_add_tail(&brd->brd_list, &brd_devices);

	return brd;
	return 0;

out_free_queue:
	blk_cleanup_queue(brd->brd_queue);
out_cleanup_disk:
	blk_cleanup_disk(disk);
out_free_dev:
	kfree(brd);
out:
	return NULL;
}

static void brd_free(struct brd_device *brd)
{
	put_disk(brd->brd_disk);
	blk_cleanup_queue(brd->brd_queue);
	brd_free_pages(brd);
	kfree(brd);
	return err;
}

static struct brd_device *brd_init_one(int i, bool *new)
{
	struct brd_device *brd;
	int err;

	*new = false;
	list_for_each_entry(brd, &brd_devices, brd_list) {
@@ -445,13 +440,14 @@ static struct brd_device *brd_init_one(int i, bool *new)
			goto out;
	}

	brd = brd_alloc(i);
	if (brd) {
		brd->brd_disk->queue = brd->brd_queue;
		add_disk(brd->brd_disk);
		list_add_tail(&brd->brd_list, &brd_devices);
	}
	*new = true;
	err = brd_alloc(i);
	if (err)
		return NULL;
	list_for_each_entry(brd, &brd_devices, brd_list) {
		if (brd->brd_number == i)
			goto out;
	}
out:
	return brd;
}
@@ -460,7 +456,9 @@ static void brd_del_one(struct brd_device *brd)
{
	list_del(&brd->brd_list);
	del_gendisk(brd->brd_disk);
	brd_free(brd);
	blk_cleanup_disk(brd->brd_disk);
	brd_free_pages(brd);
	kfree(brd);
}

static struct kobject *brd_probe(dev_t dev, int *part, void *data)
@@ -502,7 +500,7 @@ static inline void brd_check_and_reset_par(void)
static int __init brd_init(void)
{
	struct brd_device *brd, *next;
	int i;
	int err, i;

	/*
	 * brd module now has a feature to instantiate underlying device
@@ -527,22 +525,11 @@ static int __init brd_init(void)
	brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);

	for (i = 0; i < rd_nr; i++) {
		brd = brd_alloc(i);
		if (!brd)
		err = brd_alloc(i);
		if (err)
			goto out_free;
		list_add_tail(&brd->brd_list, &brd_devices);
	}

	/* point of no return */

	list_for_each_entry(brd, &brd_devices, brd_list) {
		/*
		 * associate with queue just before adding disk for
		 * avoiding to mess up failure path
		 */
		brd->brd_disk->queue = brd->brd_queue;
		add_disk(brd->brd_disk);
	}

	blk_register_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS,
				  THIS_MODULE, brd_probe, NULL, NULL);
@@ -553,14 +540,12 @@ static int __init brd_init(void)
out_free:
	debugfs_remove_recursive(brd_debugfs_dir);

	list_for_each_entry_safe(brd, next, &brd_devices, brd_list) {
		list_del(&brd->brd_list);
		brd_free(brd);
	}
	list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
		brd_del_one(brd);
	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");

	pr_info("brd: module NOT loaded !!!\n");
	return -ENOMEM;
	return err;
}

static void __exit brd_exit(void)
+12 −14
Original line number Diff line number Diff line
@@ -2129,12 +2129,12 @@ static int loop_add(struct loop_device **l, int i)
	if (err)
		goto out_free_idr;

	lo->lo_queue = blk_mq_init_queue(&lo->tag_set);
	if (IS_ERR(lo->lo_queue)) {
		err = PTR_ERR(lo->lo_queue);
	disk = lo->lo_disk = blk_mq_alloc_disk(&lo->tag_set, lo);
	if (IS_ERR(disk)) {
		err = PTR_ERR(disk);
		goto out_cleanup_tags;
	}
	lo->lo_queue->queuedata = lo;
	lo->lo_queue = lo->lo_disk->queue;

	blk_queue_max_hw_sectors(lo->lo_queue, BLK_DEF_MAX_SECTORS);

@@ -2146,11 +2146,6 @@ static int loop_add(struct loop_device **l, int i)
	 */
	blk_queue_flag_set(QUEUE_FLAG_NOMERGES, lo->lo_queue);

	err = -ENOMEM;
	disk = lo->lo_disk = alloc_disk(1 << part_shift);
	if (!disk)
		goto out_free_queue;

	/*
	 * Disable partition scanning by default. The in-kernel partition
	 * scanning can be requested individually per-device during its
@@ -2177,16 +2172,20 @@ static int loop_add(struct loop_device **l, int i)
	spin_lock_init(&lo->lo_lock);
	disk->major		= LOOP_MAJOR;
	disk->first_minor	= i << part_shift;
	disk->minors		= 1 << part_shift;
	disk->fops		= &lo_fops;
	disk->private_data	= lo;
	disk->queue		= lo->lo_queue;
	sprintf(disk->disk_name, "loop%d", i);
	add_disk(disk);
	err = add_disk_safe(disk);
	if (err)
		goto out_cleanup_disk;

	*l = lo;
	return lo->lo_number;

out_free_queue:
	blk_cleanup_queue(lo->lo_queue);
out_cleanup_disk:
	blk_cleanup_disk(disk);
out_cleanup_tags:
	blk_mq_free_tag_set(&lo->tag_set);
out_free_idr:
@@ -2200,9 +2199,8 @@ static int loop_add(struct loop_device **l, int i)
static void loop_remove(struct loop_device *lo)
{
	del_gendisk(lo->lo_disk);
	blk_cleanup_queue(lo->lo_queue);
	blk_cleanup_disk(lo->lo_disk);
	blk_mq_free_tag_set(&lo->tag_set);
	put_disk(lo->lo_disk);
	kfree(lo);
}

+27 −43
Original line number Diff line number Diff line
@@ -226,15 +226,12 @@ static const struct device_attribute pid_attr = {
static void nbd_dev_remove(struct nbd_device *nbd)
{
	struct gendisk *disk = nbd->disk;
	struct request_queue *q;

	if (disk) {
		q = disk->queue;
		del_gendisk(disk);
		blk_cleanup_queue(q);
		blk_mq_free_tag_set(&nbd->tag_set);
		disk->private_data = NULL;
		put_disk(disk);
		blk_cleanup_disk(disk);
		blk_mq_free_tag_set(&nbd->tag_set);
	}

	/*
@@ -1810,15 +1807,24 @@ static int nbd_dev_add(int index)
{
	struct nbd_device *nbd;
	struct gendisk *disk;
	struct request_queue *q;
	int err = -ENOMEM;

	nbd = kzalloc(sizeof(struct nbd_device), GFP_KERNEL);
	if (!nbd)
		goto out;

	disk = alloc_disk(1 << part_shift);
	if (!disk)
	nbd->tag_set.ops = &nbd_mq_ops;
	nbd->tag_set.nr_hw_queues = 1;
	nbd->tag_set.queue_depth = 128;
	nbd->tag_set.numa_node = NUMA_NO_NODE;
	nbd->tag_set.cmd_size = sizeof(struct nbd_cmd);
	nbd->tag_set.flags = BLK_MQ_F_SHOULD_MERGE |
		BLK_MQ_F_BLOCKING;
	nbd->tag_set.driver_data = nbd;
	nbd->destroy_complete = NULL;

	err = blk_mq_alloc_tag_set(&nbd->tag_set);
	if (err)
		goto out_free_nbd;

	if (index >= 0) {
@@ -1832,30 +1838,15 @@ static int nbd_dev_add(int index)
			index = err;
	}
	if (err < 0)
		goto out_free_disk;

		goto out_free_tags;
	nbd->index = index;
	nbd->disk = disk;
	nbd->tag_set.ops = &nbd_mq_ops;
	nbd->tag_set.nr_hw_queues = 1;
	nbd->tag_set.queue_depth = 128;
	nbd->tag_set.numa_node = NUMA_NO_NODE;
	nbd->tag_set.cmd_size = sizeof(struct nbd_cmd);
	nbd->tag_set.flags = BLK_MQ_F_SHOULD_MERGE |
		BLK_MQ_F_BLOCKING;
	nbd->tag_set.driver_data = nbd;
	nbd->destroy_complete = NULL;

	err = blk_mq_alloc_tag_set(&nbd->tag_set);
	if (err)
	disk = blk_mq_alloc_disk(&nbd->tag_set, NULL);
	if (IS_ERR(disk)) {
		err = PTR_ERR(disk);
		goto out_free_idr;

	q = blk_mq_init_queue(&nbd->tag_set);
	if (IS_ERR(q)) {
		err = PTR_ERR(q);
		goto out_free_tags;
	}
	disk->queue = q;
	nbd->disk = disk;

	/*
	 * Tell the block layer that we are not a rotational device
@@ -1875,30 +1866,23 @@ static int nbd_dev_add(int index)
	refcount_set(&nbd->refs, 1);
	INIT_LIST_HEAD(&nbd->list);
	disk->major = NBD_MAJOR;

	/* Too big first_minor can cause duplicate creation of
	 * sysfs files/links, since index << part_shift might overflow, or
	 * MKDEV() expect that the max bits of first_minor is 20.
	 */
	disk->first_minor = index << part_shift;
	if (disk->first_minor < index || disk->first_minor > MINORMASK) {
		err = -EINVAL;
		goto out_free_idr;
	}

	disk->minors = 1 << part_shift;
	disk->fops = &nbd_fops;
	disk->private_data = nbd;
	sprintf(disk->disk_name, "nbd%d", index);
	add_disk(disk);
	err = add_disk_safe(disk);
	if (err)
		goto out_err_disk;
	nbd_total_devices++;
	return index;

out_free_tags:
	blk_mq_free_tag_set(&nbd->tag_set);
out_err_disk:
	blk_cleanup_disk(disk);
out_free_idr:
	idr_remove(&nbd_index_idr, index);
out_free_disk:
	put_disk(disk);
out_free_tags:
	blk_mq_free_tag_set(&nbd->tag_set);
out_free_nbd:
	kfree(nbd);
out:
Loading