From nobody Sun Jun 21 00:15:36 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A143B2EA749; Thu, 9 Apr 2026 06:03:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775714615; cv=none; b=st1HpH9Q2IdWf1PAIj38vYClh1YcOk9YoukFGNS92wecszh9gPRn35OAWFP1ULvCe0byS0o5zKx8KOIVNvPZB0TjGTfrvSrSHii+jOgaLsw0iVjdIYiPGQoOArF16HbqGaGUTXT5nJ9vyW0tNFUgnz5F4XrvgA+mB6vJTwDRnYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775714615; c=relaxed/simple; bh=B7WAatpG02qYnXdA22elGEqNvhg/IbaWN4HchJSWzZQ=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type; b=SG6h0GbpTCWgOiTqB4VFYYXnYQN2+whXRy0JI9UhwHQsBN3/kjlxRCR3zhDn5jTHYkHiAtBV6W0jcA8JSQfN+8KKEOc6//0jfQlp/x482AcxiDed9S7MrnSgdaLdglIRpUonj/8893PIE8ovKrhQ/UCK+r3zvuEo2Vd0TXaDaDM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=kqZPPd7s; arc=none smtp.client-ip=220.197.31.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="kqZPPd7s" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version: Content-Type; bh=Jcz/JxJ17MzFPxYCiqkH/kucC2tTtE1pal3PreuZrT0=; b=kqZPPd7stIFeDwsNmwQRwrcA0p25/G+XuNKNXhsXaLrmPVqIjEEWC3xbwgLuTa sGYksLm0bzmlEoNhMQ/PrTNJX9UTEOB+wB0ZdqaqvYknrll/XPHz6BUjkTiXXitG Mrh4YN8NPzeTxBnieqhKA2DXo1OP5tOam4t4qRKkikq2c= Received: from pek-lpg-core5.wrs.com (unknown []) by gzga-smtp-mtada-g0-2 (Coremail) with SMTP id _____wBXG6fLQNdpDWpfEA--.18284S2; Thu, 09 Apr 2026 14:01:48 +0800 (CST) From: Robert Garcia To: stable@vger.kernel.org, =?UTF-8?q?Andr=C3=A9=20Draszik?= Cc: "Martin K . Petersen" , Robert Garcia , Bean Huo , Manivannan Sadhasivam , Eric Biggers , Alim Akhtar , Avri Altman , Bart Van Assche , "James E . J . Bottomley" , Sasha Levin , Peter Wang , Wang Shuaiwei , Eric Biggers , Manish Pandey , Brian Kao , Greg Kroah-Hartman , Adrian Hunter , Archana Patni , Arnd Bergmann , Jens Axboe , Ulf Hansson , Mike Snitzer , Satya Tangirala , linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6.6.y] scsi: ufs: core: Fix use-after free in init error and remove paths Date: Thu, 9 Apr 2026 14:01:47 +0800 Message-Id: <20260409060147.3175811-1-rob_garcia@163.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBXG6fLQNdpDWpfEA--.18284S2 X-Coremail-Antispam: 1Uf129KBjvJXoWxtw13XFWfGw4DWryDKrWkCrg_yoW3uw4kpF WYqay5Ar4kKr42gr1DJw48CFyrKw4xG345GrZ2934ruw1jkFn3Wa4vyF109F15GFZxZ3Wj qFWjyr48u3WUZaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0zi_Ma8UUUUU= X-CM-SenderInfo: 5uresw5dufxti6rwjhhfrp/xtbC5g2T-mnXQM2akQAA3+ From: Andr=C3=A9 Draszik [ Upstream commit f8fb2403ddebb5eea0033d90d9daae4c88749ada ] devm_blk_crypto_profile_init() registers a cleanup handler to run when the associated (platform-) device is being released. For UFS, the crypto private data and pointers are stored as part of the ufs_hba's data structure 'struct ufs_hba::crypto_profile'. This structure is allocated as part of the underlying ufshcd and therefore Scsi_host allocation. During driver release or during error handling in ufshcd_pltfrm_init(), this structure is released as part of ufshcd_dealloc_host() before the (platform-) device associated with the crypto call above is released. Once this device is released, the crypto cleanup code will run, using the just-released 'struct ufs_hba::crypto_profile'. This causes a use-after-free situation: Call trace: kfree+0x60/0x2d8 (P) kvfree+0x44/0x60 blk_crypto_profile_destroy_callback+0x28/0x70 devm_action_release+0x1c/0x30 release_nodes+0x6c/0x108 devres_release_all+0x98/0x100 device_unbind_cleanup+0x20/0x70 really_probe+0x218/0x2d0 In other words, the initialisation code flow is: platform-device probe ufshcd_pltfrm_init() ufshcd_alloc_host() scsi_host_alloc() allocation of struct ufs_hba creation of scsi-host devices devm_blk_crypto_profile_init() devm registration of cleanup handler using platform-device and during error handling of ufshcd_pltfrm_init() or during driver removal: ufshcd_dealloc_host() scsi_host_put() put_device(scsi-host) release of struct ufs_hba put_device(platform-device) crypto cleanup handler To fix this use-after free, change ufshcd_alloc_host() to register a devres action to automatically cleanup the underlying SCSI device on ufshcd destruction, without requiring explicit calls to ufshcd_dealloc_host(). This way: * the crypto profile and all other ufs_hba-owned resources are destroyed before SCSI (as they've been registered after) * a memleak is plugged in tc-dwc-g210-pci.c remove() as a side-effect * EXPORT_SYMBOL_GPL(ufshcd_dealloc_host) can be removed fully as it's not needed anymore * no future drivers using ufshcd_alloc_host() could ever forget adding the cleanup Fixes: cb77cb5abe1f ("blk-crypto: rename blk_keyslot_manager to blk_crypto_= profile") Fixes: d76d9d7d1009 ("scsi: ufs: use devm_blk_ksm_init()") Cc: stable@vger.kernel.org Signed-off-by: Andr=C3=A9 Draszik Link: https://lore.kernel.org/r/20250124-ufshcd-fix-v4-1-c5d0144aae59@linar= o.org Reviewed-by: Bean Huo Reviewed-by: Manivannan Sadhasivam Acked-by: Eric Biggers Signed-off-by: Martin K. Petersen [ Delete modifications about ufshcd_parse_operating_points() for it's added= from commit 72208ebe181e3("scsi: ufs: core: Add support for parsing OPP")=20 and that in ufshcd_pltfrm_remove() for it's added from commit=20 897df60c16d54("scsi: ufs: pltfrm: Dellocate HBA during ufshcd_pltfrm_remove= ()"). ] Signed-off-by: Robert Garcia --- drivers/ufs/core/ufshcd.c | 31 +++++++++++++++++++++---------- drivers/ufs/host/ufshcd-pci.c | 2 -- drivers/ufs/host/ufshcd-pltfrm.c | 25 ++++++++----------------- include/ufs/ufshcd.h | 1 - 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 2dcb0146c17e..f6aada5150f9 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -10475,16 +10475,6 @@ int ufshcd_system_thaw(struct device *dev) EXPORT_SYMBOL_GPL(ufshcd_system_thaw); #endif /* CONFIG_PM_SLEEP */ =20 -/** - * ufshcd_dealloc_host - deallocate Host Bus Adapter (HBA) - * @hba: pointer to Host Bus Adapter (HBA) - */ -void ufshcd_dealloc_host(struct ufs_hba *hba) -{ - scsi_host_put(hba->host); -} -EXPORT_SYMBOL_GPL(ufshcd_dealloc_host); - /** * ufshcd_set_dma_mask - Set dma mask based on the controller * addressing capability @@ -10503,12 +10493,26 @@ static int ufshcd_set_dma_mask(struct ufs_hba *hb= a) return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32)); } =20 +/** + * ufshcd_devres_release - devres cleanup handler, invoked during release = of + * hba->dev + * @host: pointer to SCSI host + */ +static void ufshcd_devres_release(void *host) +{ + scsi_host_put(host); +} + /** * ufshcd_alloc_host - allocate Host Bus Adapter (HBA) * @dev: pointer to device handle * @hba_handle: driver private handle * * Return: 0 on success, non-zero value on failure. + * + * NOTE: There is no corresponding ufshcd_dealloc_host() because this func= tion + * keeps track of its allocations using devres and deallocates everything = on + * device removal automatically. */ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle) { @@ -10530,6 +10534,13 @@ int ufshcd_alloc_host(struct device *dev, struct u= fs_hba **hba_handle) err =3D -ENOMEM; goto out_error; } + + err =3D devm_add_action_or_reset(dev, ufshcd_devres_release, + host); + if (err) + return dev_err_probe(dev, err, + "failed to add ufshcd dealloc action\n"); + host->nr_maps =3D HCTX_TYPE_POLL + 1; hba =3D shost_priv(host); hba->host =3D host; diff --git a/drivers/ufs/host/ufshcd-pci.c b/drivers/ufs/host/ufshcd-pci.c index 4ecaaf52b3e9..3ff799497191 100644 --- a/drivers/ufs/host/ufshcd-pci.c +++ b/drivers/ufs/host/ufshcd-pci.c @@ -620,7 +620,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) pm_runtime_forbid(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); ufshcd_remove(hba); - ufshcd_dealloc_host(hba); } =20 /** @@ -665,7 +664,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci= _device_id *id) err =3D ufshcd_init(hba, mmio_base, pdev->irq); if (err) { dev_err(&pdev->dev, "Initialization failed\n"); - ufshcd_dealloc_host(hba); return err; } =20 diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-plt= frm.c index 797a4dfe45d9..0112ecbebe46 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -339,21 +339,17 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, struct device *dev =3D &pdev->dev; =20 mmio_base =3D devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(mmio_base)) { - err =3D PTR_ERR(mmio_base); - goto out; - } + if (IS_ERR(mmio_base)) + return PTR_ERR(mmio_base); =20 irq =3D platform_get_irq(pdev, 0); - if (irq < 0) { - err =3D irq; - goto out; - } + if (irq < 0) + return irq; =20 err =3D ufshcd_alloc_host(dev, &hba); if (err) { dev_err(dev, "Allocation failed\n"); - goto out; + return err; } =20 hba->vops =3D vops; @@ -362,13 +358,13 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, if (err) { dev_err(dev, "%s: clock parse failed %d\n", __func__, err); - goto dealloc_host; + return err; } err =3D ufshcd_parse_regulator_info(hba); if (err) { dev_err(dev, "%s: regulator init failed %d\n", __func__, err); - goto dealloc_host; + return err; } =20 ufshcd_init_lanes_per_dir(hba); @@ -377,18 +373,13 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, if (err) { dev_err_probe(dev, err, "Initialization failed with error %d\n", err); - goto dealloc_host; + return err; } =20 pm_runtime_set_active(dev); pm_runtime_enable(dev); =20 return 0; - -dealloc_host: - ufshcd_dealloc_host(hba); -out: - return err; } EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init); =20 diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 8d2efb9e5d66..60942ed0040f 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1286,7 +1286,6 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u= 32 mask, u32 val, u32 reg) } =20 int ufshcd_alloc_host(struct device *, struct ufs_hba **); -void ufshcd_dealloc_host(struct ufs_hba *); int ufshcd_hba_enable(struct ufs_hba *hba); int ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int); int ufshcd_link_recovery(struct ufs_hba *hba); --=20 2.34.1