Skip to contentSkip to conversation

spi: controller registration fixes

PATCH In review Johan Hovold 2 participants 8 messages Mar 12 – Mar 17

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover spi: controller registration fixes

This series fixes a few issues related to controller registration found through inspection.

Johan

Johan Hovold (5):
spi: fix use-after-free on controller registration failure
spi: fix statistics allocation
spi: drop unused devres statistics allocation
spi: fix misleading controller registration kernel-doc
spi: fix misleading controller deregistration kernel-doc

 drivers/spi/spi.c | 60 +++++++++++++++++++++++------------------------
 1 file changed, 29 insertions(+), 31 deletions(-)
Signature · 1 line
2.52.0
#1 lore raw

PATCH 1/5 spi: fix use-after-free on controller registration failure

Make sure to deregister from driver core also in the unlikely event that per-cpu statistics allocation fails during controller registration to avoid use-after-free (of driver resources) and unclocked register accesses.

Fixes 6598b91b5ac3 ("spi: spi.c: Convert statistics to per-cpu u64_stats_t")
Cc David Jander <[email protected]>
---
 drivers/spi/spi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/spi/spi.c +4 -4
index 61f7bde8c7fb..9b2e307dc30a 100644
@@ -3480,10 +3480,8 @@ int spi_register_controller(struct spi_controller *ctlr)
 		dev_info(dev, "controller is unqueued, this is deprecated\n");
 	} else if (ctlr->transfer_one || ctlr->transfer_one_message) {
 		status = spi_controller_initialize_queue(ctlr);
-		if (status) {
-			device_del(&ctlr->dev);
-			goto free_bus_id;
-		}
+		if (status)
+			goto del_ctrl;
 	}
 	/* Add statistics */
 	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(dev);
@@ -3506,6 +3504,8 @@ int spi_register_controller(struct spi_controller *ctlr)
 
 destroy_queue:
 	spi_destroy_queue(ctlr);
+del_ctrl:
+	device_del(&ctlr->dev);
 free_bus_id:
 	mutex_lock(&board_lock);
 	idr_remove(&spi_controller_idr, ctlr->bus_num);
Signature · 1 line
2.52.0
#2 lore raw

PATCH 2/5 spi: fix statistics allocation

In reply to Johan Hovold

The controller per-cpu statistics is not allocated until after the controller has been registered with driver core, which leaves a window where accessing the sysfs attributes can trigger a NULL-pointer dereference.

Fix this by moving the statistics allocation to controller allocation while tying its lifetime to that of the controller (rather than using implicit devres).

Fixes 6598b91b5ac3 ("spi: spi.c: Convert statistics to per-cpu u64_stats_t")
Cc David Jander <[email protected]>
---
 drivers/spi/spi.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
drivers/spi/spi.c +8 -9
index 9b2e307dc30a..53dee314d76a 100644
@@ -3049,6 +3049,8 @@ static void spi_controller_release(struct device *dev)
 	struct spi_controller *ctlr;
 
 	ctlr = container_of(dev, struct spi_controller, dev);
+
+	free_percpu(ctlr->pcpu_statistics);
 	kfree(ctlr);
 }
 
@@ -3192,6 +3194,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
 	if (!ctlr)
 		return NULL;
 
+	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL);
+	if (!ctlr->pcpu_statistics) {
+		kfree(ctlr);
+		return NULL;
+	}
+
 	device_initialize(&ctlr->dev);
 	INIT_LIST_HEAD(&ctlr->queue);
 	spin_lock_init(&ctlr->queue_lock);
@@ -3483,13 +3491,6 @@ int spi_register_controller(struct spi_controller *ctlr)
 		if (status)
 			goto del_ctrl;
 	}
-	/* Add statistics */
-	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(dev);
-	if (!ctlr->pcpu_statistics) {
-		dev_err(dev, "Error allocating per-cpu statistics\n");
-		status = -ENOMEM;
-		goto destroy_queue;
-	}
 
 	mutex_lock(&board_lock);
 	list_add_tail(&ctlr->list, &spi_controller_list);
@@ -3502,8 +3503,6 @@ int spi_register_controller(struct spi_controller *ctlr)
 	acpi_register_spi_devices(ctlr);
 	return status;
 
-destroy_queue:
-	spi_destroy_queue(ctlr);
 del_ctrl:
 	device_del(&ctlr->dev);
 free_bus_id:
Signature · 1 line
2.52.0
#3 lore raw

PATCH 3/5 spi: drop unused devres statistics allocation

In reply to Johan Hovold

Drop the now unused device managed per-cpu statistics allocation.

---
 drivers/spi/spi.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)
drivers/spi/spi.c +12 -15
index 53dee314d76a..bfc42b75549a 100644
@@ -96,25 +96,22 @@ static ssize_t driver_override_show(struct device *dev,
 }
 static DEVICE_ATTR_RW(driver_override);
 
-static struct spi_statistics __percpu *spi_alloc_pcpu_stats(struct device *dev)
+static struct spi_statistics __percpu *spi_alloc_pcpu_stats(void)
 {
 	struct spi_statistics __percpu *pcpu_stats;
+	int cpu;
 
-	if (dev)
-		pcpu_stats = devm_alloc_percpu(dev, struct spi_statistics);
-	else
-		pcpu_stats = alloc_percpu_gfp(struct spi_statistics, GFP_KERNEL);
-
-	if (pcpu_stats) {
-		int cpu;
+	pcpu_stats = alloc_percpu_gfp(struct spi_statistics, GFP_KERNEL);
+	if (!pcpu_stats)
+		return NULL;
 
-		for_each_possible_cpu(cpu) {
-			struct spi_statistics *stat;
+	for_each_possible_cpu(cpu) {
+		struct spi_statistics *stat;
 
-			stat = per_cpu_ptr(pcpu_stats, cpu);
-			u64_stats_init(&stat->syncp);
-		}
+		stat = per_cpu_ptr(pcpu_stats, cpu);
+		u64_stats_init(&stat->syncp);
 	}
+
 	return pcpu_stats;
 }
 
@@ -574,7 +571,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
 		return NULL;
 	}
 
-	spi->pcpu_statistics = spi_alloc_pcpu_stats(NULL);
+	spi->pcpu_statistics = spi_alloc_pcpu_stats();
 	if (!spi->pcpu_statistics) {
 		kfree(spi);
 		spi_controller_put(ctlr);
@@ -3194,7 +3191,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
 	if (!ctlr)
 		return NULL;
 
-	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL);
+	ctlr->pcpu_statistics = spi_alloc_pcpu_stats();
 	if (!ctlr->pcpu_statistics) {
 		kfree(ctlr);
 		return NULL;
Signature · 1 line
2.52.0
#4 lore raw

PATCH 4/5 spi: fix misleading controller registration kernel-doc

In reply to Johan Hovold

The controller reference count is not decremented on registration failures (and has not been for a very long time) contrary to what the outdated kernel-doc says.

Drop the entire sentence about return values which are now documented in the Return section.

Fixes b885244eb262 ("[PATCH] spi: add spi_driver to SPI framework")
---
 drivers/spi/spi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/spi/spi.c +2 -2
index bfc42b75549a..34aca18a96d8 100644
@@ -3388,8 +3388,8 @@ static int spi_controller_id_alloc(struct spi_controller *ctlr, int start, int e
  * device identification, boards need configuration tables telling which
  * chip is at which address.
  *
- * This must be called from context that can sleep.  It returns zero on
- * success, else a negative error code (dropping the controller's refcount).
+ * This must be called from context that can sleep.
+ *
  * After a successful return, the caller is responsible for calling
  * spi_unregister_controller().
  *
Signature · 1 line
2.52.0
#5 lore raw

PATCH 5/5 spi: fix misleading controller deregistration kernel-doc

In reply to Johan Hovold

The controller reference count is not decremented on deregistration if the controller has been allocated using devm_spi_alloc_host/target().

Amend the kernel-doc for devm_spi_register_controller() and spi_unregister_controller() so that it reflects this (more recent) behaviour.

Fixes 5e844cc37a5c ("spi: Introduce device-managed SPI controller allocation")
---
 drivers/spi/spi.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/spi/spi.c +4 -2
index 34aca18a96d8..b5e2f1e1a89e 100644
@@ -3523,7 +3523,8 @@ static void devm_spi_unregister_controller(void *ctlr)
  * Context: can sleep
  *
  * Register a SPI device as with spi_register_controller() which will
- * automatically be unregistered and freed.
+ * automatically be unregistered (and freed unless it has been allocated using
+ * devm_spi_alloc_host/target()).
  *
  * Return: zero on success, else a negative error code.
  */
@@ -3557,7 +3558,8 @@ static int __unregister(struct device *dev, void *null)
  *
  * This must be called from context that can sleep.
  *
- * Note that this function also drops a reference to the controller.
+ * Note that this function also drops a reference to the controller unless it
+ * has been allocated using devm_spi_alloc_host/target().
  */
 void spi_unregister_controller(struct spi_controller *ctlr)
 {
Signature · 1 line
2.52.0
maintainer
#6 lore raw
In reply to Johan Hovold
Quoted 8 lines · Johan Hovold

spi: controller registration fixes

This series fixes a few issues related to controller registration found through inspection.

Johan

[...]

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-7.1

Thanks!

[1/5] spi: fix use-after-free on controller registration failure

      https://git.kernel.org/broonie/spi/c/8634e05b08ea
[2/5] spi: fix statistics allocation
      https://git.kernel.org/broonie/spi/c/dee0774bbb2a
[3/5] spi: drop unused devres statistics allocation
      https://git.kernel.org/broonie/spi/c/d5b4cb41b9a2
[4/5] spi: fix misleading controller registration kernel-doc
      https://git.kernel.org/broonie/spi/c/edc463d72d69
[5/5] spi: fix misleading controller deregistration kernel-doc
      https://git.kernel.org/broonie/spi/c/3f174274d224

All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying to this mail.

Thanks,
Mark

maintainer
#7 lore raw
In reply to Johan Hovold
Quoted 6 lines · Johan Hovold

This series fixes a few issues related to controller registration found through inspection.

Johan

Quoted 8 lines

Johan Hovold (5):
spi: fix use-after-free on controller registration failure
spi: fix statistics allocation
spi: drop unused devres statistics allocation
spi: fix misleading controller registration kernel-doc
spi: fix misleading controller deregistration kernel-doc

[...]

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/5] spi: fix use-after-free on controller registration failure

      https://git.kernel.org/broonie/misc/c/8634e05b08ea
[2/5] spi: fix statistics allocation
      https://git.kernel.org/broonie/misc/c/dee0774bbb2a
[3/5] spi: drop unused devres statistics allocation
      https://git.kernel.org/broonie/misc/c/d5b4cb41b9a2
[4/5] spi: fix misleading controller registration kernel-doc
      https://git.kernel.org/broonie/misc/c/edc463d72d69
[5/5] spi: fix misleading controller deregistration kernel-doc
      https://git.kernel.org/broonie/misc/c/3f174274d224

All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying to this mail.

Thanks,
Mark