[PATCH] spi: fix controller reference leak in acpi_spi_device_alloc()

Wentao Liang posted 1 patch 1 week ago
drivers/spi/spi.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
[PATCH] spi: fix controller reference leak in acpi_spi_device_alloc()
Posted by Wentao Liang 1 week ago
acpi_spi_add_resource() stores the controller returned by
acpi_spi_find_controller_by_adev() in lookup->ctlr. That lookup takes a
reference via class_find_device(), which acpi_spi_device_alloc() never
releases, leaking it on the error paths and on the success path too,
where spi_alloc_device() takes its own reference. Drop the lookup
reference when the caller did not pass a controller.

Fixes: 87e59b36e5e2 ("spi: Support selection of the index of the ACPI Spi Resource before alloc")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
 drivers/spi/spi.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 104279858f56..fb5e17d55801 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2979,9 +2979,12 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
 				     acpi_spi_add_resource, &lookup);
 	acpi_dev_free_resource_list(&resource_list);
 
-	if (ret < 0)
+	if (ret < 0) {
 		/* Found SPI in _CRS but it points to another controller */
+		if (!ctlr)
+			spi_controller_put(lookup.ctlr);
 		return ERR_PTR(ret);
+	}
 
 	if (!lookup.max_speed_hz &&
 	    ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) &&
@@ -2990,13 +2993,18 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
 		acpi_spi_parse_apple_properties(adev, &lookup);
 	}
 
-	if (!lookup.max_speed_hz)
+	if (!lookup.max_speed_hz) {
+		if (!ctlr)
+			spi_controller_put(lookup.ctlr);
 		return ERR_PTR(-ENODEV);
+	}
 
 	spi = spi_alloc_device(lookup.ctlr);
 	if (!spi) {
 		dev_err(&lookup.ctlr->dev, "failed to allocate SPI device for %s\n",
 			dev_name(&adev->dev));
+		if (!ctlr)
+			spi_controller_put(lookup.ctlr);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -3013,6 +3021,14 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
 	 */
 	spi->cs_index_mask	= BIT(0);
 
+	/*
+	 * If the controller was looked up from the ACPI resource, release the
+	 * reference taken by acpi_spi_find_controller_by_adev(). The new SPI
+	 * device holds the reference taken by spi_alloc_device() instead.
+	 */
+	if (!ctlr)
+		spi_controller_put(lookup.ctlr);
+
 	return spi;
 }
 EXPORT_SYMBOL_GPL(acpi_spi_device_alloc);
-- 
2.34.1
Re: [PATCH] spi: fix controller reference leak in acpi_spi_device_alloc()
Posted by Mark Brown 1 week ago
On Thu, Sep 17, 2026 at 03:48:26PM +0000, Wentao Liang wrote:
> acpi_spi_add_resource() stores the controller returned by
> acpi_spi_find_controller_by_adev() in lookup->ctlr. That lookup takes a
> reference via class_find_device(), which acpi_spi_device_alloc() never
> releases, leaking it on the error paths and on the success path too,
> where spi_alloc_device() takes its own reference. Drop the lookup
> reference when the caller did not pass a controller.

This doesn't apply against current code, please check and resend.