diff options
author | Boris Brezillon <boris.brezillon@bootlin.com> | 2018-04-11 01:44:30 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-04-26 15:53:29 +0300 |
commit | bdf3a3b59a7ab1972e7d2242c9466ba7e79f0004 (patch) | |
tree | 908e4ca051d1936ec6dbdca0f300165cd061cfcc | |
parent | 0d7412ed1f5dc0858eb4f29650a8c9c5cce8b285 (diff) | |
download | linux-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.c | 21 |
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) |