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

!13337 fix CVE-2024-50135

Merge Pull Request from: @ci-robot 
 
PR sync from: Zheng Qixing <zhengqixing@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/RCCTN3KFGW75QFIQOH7HHXFUD4FPOMBM/ 
fix CVE-2024-50135.

Christoph Hellwig (2):
  nvme-pci: split nvme_dev_add
  nvme-pci: refactor the tagset handling in nvme_reset_work

Maurizio Lombardi (1):
  nvme-pci: fix race condition between reset and nvme_dev_disable()


-- 
2.39.2
 
https://gitee.com/src-openeuler/kernel/issues/IB2BXE 
 
Link:https://gitee.com/openeuler/kernel/pulls/13337

 

Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarLi Nan <linan122@huawei.com>
Signed-off-by: default avatarLi Nan <linan122@huawei.com>
parents f86196bf 5cd308df
Loading
Loading
Loading
Loading
+73 −46
Original line number Diff line number Diff line
@@ -2317,23 +2317,22 @@ static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
	return true;
}

static void nvme_dev_add(struct nvme_dev *dev)
static void nvme_pci_alloc_tag_set(struct nvme_dev *dev)
{
	struct blk_mq_tag_set * set = &dev->tagset;
	int ret;

	if (!dev->ctrl.tagset) {
		dev->tagset.ops = &nvme_mq_ops;
		dev->tagset.nr_hw_queues = dev->online_queues - 1;
		dev->tagset.nr_maps = 2; /* default + read */
	set->ops = &nvme_mq_ops;
	set->nr_hw_queues = dev->online_queues - 1;
	set->nr_maps = 2; /* default + read */
	if (dev->io_queues[HCTX_TYPE_POLL])
			dev->tagset.nr_maps++;
		dev->tagset.timeout = NVME_IO_TIMEOUT;
		dev->tagset.numa_node = dev->ctrl.numa_node;
		dev->tagset.queue_depth = min_t(unsigned int, dev->q_depth,
						BLK_MQ_MAX_DEPTH) - 1;
		dev->tagset.cmd_size = sizeof(struct nvme_iod);
		dev->tagset.flags = BLK_MQ_F_SHOULD_MERGE;
		dev->tagset.driver_data = dev;
		set->nr_maps++;
	set->timeout = NVME_IO_TIMEOUT;
	set->numa_node = dev->ctrl.numa_node;
	set->queue_depth = min_t(unsigned, dev->q_depth, BLK_MQ_MAX_DEPTH) - 1;
	set->cmd_size = sizeof(struct nvme_iod);
	set->flags = BLK_MQ_F_SHOULD_MERGE;
	set->driver_data = dev;

	/*
	 * Some Apple controllers requires tags to be unique
@@ -2341,23 +2340,34 @@ static void nvme_dev_add(struct nvme_dev *dev)
	 * tags of the IO queue.
	 */
	if (dev->ctrl.quirks & NVME_QUIRK_SHARED_TAGS)
			dev->tagset.reserved_tags = NVME_AQ_DEPTH;
		set->reserved_tags = NVME_AQ_DEPTH;

		ret = blk_mq_alloc_tag_set(&dev->tagset);
	ret = blk_mq_alloc_tag_set(set);
	if (ret) {
		dev_warn(dev->ctrl.device,
			"IO queues tagset allocation failed %d\n", ret);
		return;
	}
		dev->ctrl.tagset = &dev->tagset;
	} else {
		blk_mq_update_nr_hw_queues(&dev->tagset, dev->online_queues - 1);
	dev->ctrl.tagset = set;
}

		/* Free previously allocated queues that are no longer usable */
		nvme_free_queues(dev, dev->online_queues);
static bool nvme_pci_update_nr_queues(struct nvme_dev *dev)
{
	/* Give up if we are racing with nvme_dev_disable() */
	if (!mutex_trylock(&dev->shutdown_lock))
		return false;

	/* Check if nvme_dev_disable() has been executed already */
	if (!dev->online_queues) {
		mutex_unlock(&dev->shutdown_lock);
		return false;
	}

	nvme_dbbuf_set(dev);
	blk_mq_update_nr_hw_queues(&dev->tagset, dev->online_queues - 1);
	/* free previously allocated queues that are no longer usable */
	nvme_free_queues(dev, dev->online_queues);
	mutex_unlock(&dev->shutdown_lock);
	return true;
}

static int nvme_pci_enable(struct nvme_dev *dev)
@@ -2704,20 +2714,37 @@ static void nvme_reset_work(struct work_struct *work)
	if (result)
		goto out;

	if (dev->ctrl.tagset) {
		/*
	 * Keep the controller around but remove all namespaces if we don't have
	 * any working I/O queue.
		 * This is a controller reset and we already have a tagset.
		 * Freeze and update the number of I/O queues as thos might have
		 * changed.  If there are no I/O queues left after this reset,
		 * keep the controller around but remove all namespaces.
		 */
	if (dev->online_queues < 2) {
		dev_warn(dev->ctrl.device, "IO queues not created\n");
		if (dev->online_queues > 1) {
			nvme_start_queues(&dev->ctrl);
			nvme_wait_freeze(&dev->ctrl);
			if (!nvme_pci_update_nr_queues(dev))
				goto out;
			nvme_dbbuf_set(dev);
			nvme_unfreeze(&dev->ctrl);
		} else {
			dev_warn(dev->ctrl.device, "IO queues lost\n");
			nvme_kill_queues(&dev->ctrl);
			nvme_remove_namespaces(&dev->ctrl);
			nvme_free_tagset(dev);
		}
	} else {
		nvme_start_queues(&dev->ctrl);
		nvme_wait_freeze(&dev->ctrl);
		nvme_dev_add(dev);
		nvme_unfreeze(&dev->ctrl);
		/*
		 * First probe.  Still allow the controller to show up even if
		 * there are no namespaces.
		 */
		if (dev->online_queues > 1) {
			nvme_pci_alloc_tag_set(dev);
			nvme_dbbuf_set(dev);
		} else {
			dev_warn(dev->ctrl.device, "IO queues not created\n");
		}
	}

	/*