summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@bootlin.com>2018-04-11 01:44:30 +0300
committerMark Brown <broonie@kernel.org>2018-04-26 15:53:29 +0300
commitbdf3a3b59a7ab1972e7d2242c9466ba7e79f0004 (patch)
tree908e4ca051d1936ec6dbdca0f300165cd061cfcc
parent0d7412ed1f5dc0858eb4f29650a8c9c5cce8b285 (diff)
downloadlinux-bdf3a3b59a7ab1972e7d2242c9466ba7e79f0004.tar.xz
spi: Check presence the of ->transfer[_xxx]() before registering a controller
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> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 3f4666365678..9ab65fb2738e 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2068,6 +2068,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
@@ -2101,6 +2114,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)