lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 21 Mar 2021 18:43:32 -0700
From:   Dmitry Torokhov <dmitry.torokhov@...il.com>
To:     Mark Brown <broonie@...nel.org>
Cc:     linux-spi@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] spi: ensure timely release of driver-allocated resources

More and more drivers rely on devres to manage their resources, however
if bus' probe() and release() methods are not trivial and control some
of resources as well (for example enable or disable clocks, or attach
device to a power domain), we need to make sure that driver-allocated
resources are released immediately after driver's remove() method
returns, and not postponed until driver core gets around to releasing
resources. To fix that we open a new devres group before calling
driver's probe() and explicitly release it when we return from driver's
remove().

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@...il.com>
---

Note that this is not SPI-specific issue. I already send a similar
patch for I2C and will be sending more.

 drivers/spi/spi.c       | 25 +++++++++++++++++++++++--
 include/linux/spi/spi.h |  4 ++++
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c19a09201358..7c369cebebbd 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -421,29 +421,50 @@ static int spi_probe(struct device *dev)
 	if (ret)
 		return ret;
 
+	spi->devres_group_id = devres_open_group(dev, NULL, GFP_KERNEL);
+	if (!spi->devres_group_id) {
+		ret = -ENOMEM;
+		goto err_detach_pm_domain;
+	}
+
 	if (sdrv->probe) {
 		ret = sdrv->probe(spi);
 		if (ret)
-			dev_pm_domain_detach(dev, true);
+			goto err_release_driver_resources;
 	}
 
+	/*
+	 * Note that we are not closing the devres group opened above so
+	 * even resources that were attached to the device after probe has
+	 * run are released when spi_remove() is executed. This is needed as
+	 * some drivers might allocate additional resources.
+	 */
+
+	return 0;
+
+err_release_driver_resources:
+	devres_release_group(dev, spi->devres_group_id);
+err_detach_pm_domain:
+	dev_pm_domain_detach(dev, true);
 	return ret;
 }
 
 static int spi_remove(struct device *dev)
 {
 	const struct spi_driver		*sdrv = to_spi_driver(dev->driver);
+	struct spi_device		*spi = to_spi_device(dev);
 
 	if (sdrv->remove) {
 		int ret;
 
-		ret = sdrv->remove(to_spi_device(dev));
+		ret = sdrv->remove(spi);
 		if (ret)
 			dev_warn(dev,
 				 "Failed to unbind driver (%pe), ignoring\n",
 				 ERR_PTR(ret));
 	}
 
+	devres_release_group(dev, spi->devres_group_id);
 	dev_pm_domain_detach(dev, true);
 
 	return 0;
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index aa09fdc8042d..969dd8ccc657 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -144,6 +144,8 @@ extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer);
  *	not using a GPIO line)
  * @word_delay: delay to be inserted between consecutive
  *	words of a transfer
+ * @devres_group_id: id of the devres group that will be created for resources
+ *	acquired when probing this device.
  *
  * @statistics: statistics for the spi_device
  *
@@ -195,6 +197,8 @@ struct spi_device {
 	struct gpio_desc	*cs_gpiod;	/* chip select gpio desc */
 	struct spi_delay	word_delay; /* inter-word delay */
 
+	void			*devres_group_id;
+
 	/* the statistics */
 	struct spi_statistics	statistics;
 
-- 
2.31.0.rc2.261.g7f71774620-goog


-- 
Dmitry

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ