Commit 6afca39a authored by Keith Busch's avatar Keith Busch Committed by Liu Shixin
Browse files

nvme: apple: fix device reference counting

mainline inclusion
from mainline-v6.11-rc1
commit b9ecbfa45516182cd062fecd286db7907ba84210
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAMMBA
CVE: CVE-2024-43913

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b9ecbfa45516182cd062fecd286db7907ba84210



--------------------------------

Drivers must call nvme_uninit_ctrl after a successful nvme_init_ctrl.
Split the allocation side out to make the error handling boundary easier
to navigate. The apple driver had been doing this wrong, leaking the
controller device memory on a tagset failure.

Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarChaitanya Kulkarni <kch@nvidia.com>
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
Conflicts:
	drivers/nvme/host/apple.c
[ Conflicts because blk_mq_init_queue due to commit 9ac4dd8c47d5
  ("block: pass a queue_limits argument to blk_mq_init_queue") ]
Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent 9e3d5ec1
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -1387,7 +1387,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
	mempool_destroy(data);
}

static int apple_nvme_probe(struct platform_device *pdev)
static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct apple_nvme *anv;
@@ -1395,7 +1395,7 @@ static int apple_nvme_probe(struct platform_device *pdev)

	anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
	if (!anv)
		return -ENOMEM;
		return ERR_PTR(-ENOMEM);

	anv->dev = get_device(dev);
	anv->adminq.is_adminq = true;
@@ -1515,10 +1515,26 @@ static int apple_nvme_probe(struct platform_device *pdev)
		goto put_dev;
	}

	return anv;
put_dev:
	put_device(anv->dev);
	return ERR_PTR(ret);
}

static int apple_nvme_probe(struct platform_device *pdev)
{
	struct apple_nvme *anv;
	int ret;

	anv = apple_nvme_alloc(pdev);
	if (IS_ERR(anv))
		return PTR_ERR(anv);

	anv->ctrl.admin_q = blk_mq_init_queue(&anv->admin_tagset);
	if (IS_ERR(anv->ctrl.admin_q)) {
		ret = -ENOMEM;
		goto put_dev;
		anv->ctrl.admin_q = NULL;
		goto out_uninit_ctrl;
	}

	nvme_reset_ctrl(&anv->ctrl);
@@ -1526,8 +1542,9 @@ static int apple_nvme_probe(struct platform_device *pdev)

	return 0;

put_dev:
	put_device(anv->dev);
out_uninit_ctrl:
	nvme_uninit_ctrl(&anv->ctrl);
	nvme_put_ctrl(&anv->ctrl);
	return ret;
}