[v2,01/10] spi: Check presence the of ->transfer[_xxx]() before registering a controller

Message ID 20180410224439.9260-2-boris.brezillon@bootlin.com
State Changes Requested
Headers show
Series
  • spi: Extend the framework to generically support memory devices
Related show

Commit Message

Boris Brezillon April 10, 2018, 10:44 p.m.
Right now, no checks are done on the presence of a ->transfer[_xxx]()
method, which can lead to a NULL pointer dereference when someone
starts sending something on the bus.

Do the check at registration time and refuse to add the controller if
all ->transfer[_xxx]() pointers are NULL.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
---
 drivers/spi/spi.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Patch

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 7b213faa0a2b..24369e437c6b 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2063,6 +2063,19 @@  static int of_spi_register_master(struct spi_controller *ctlr)
 }
 #endif
 
+static int spi_controller_check_ops(struct spi_controller *ctlr)
+{
+	/*
+	 * The controller must at least implement one of the ->transfer()
+	 * hooks.
+	 */
+	if (!ctlr->transfer && !ctlr->transfer_one &&
+	    !ctlr->transfer_one_message)
+		return -EINVAL;
+
+	return 0;
+}
+
 /**
  * spi_register_controller - register SPI master or slave controller
  * @ctlr: initialized master, originally from spi_alloc_master() or
@@ -2096,6 +2109,14 @@  int spi_register_controller(struct spi_controller *ctlr)
 	if (!dev)
 		return -ENODEV;
 
+	/*
+	 * Make sure all necessary hooks are implemented before registering
+	 * the SPI controller.
+	 */
+	status = spi_controller_check_ops(ctlr);
+	if (status)
+		return status;
+
 	if (!spi_controller_is_slave(ctlr)) {
 		status = of_spi_register_master(ctlr);
 		if (status)