Skip to content

Commit e1483ac

Browse files
l1kbroonie
authored andcommitted
spi: bcm2835: Fix use-after-free on unbind
bcm2835_spi_remove() accesses the driver's private data after calling spi_unregister_controller() even though that function releases the last reference on the spi_controller and thereby frees the private data. Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound. Fixes: f804387 ("spi: add driver for BCM2835") Reported-by: Sascha Hauer <s.hauer@pengutronix.de> Reported-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: Lukas Wunner <lukas@wunner.de> Cc: <stable@vger.kernel.org> # v3.10+: 123456789abc: spi: Introduce device-managed SPI controller allocation Cc: <stable@vger.kernel.org> # v3.10+ Cc: Vladimir Oltean <olteanv@gmail.com> Tested-by: Florian Fainelli <f.fainelli@gmail.com> Acked-by: Florian Fainelli <f.fainelli@gmail.com> Link: https://lore.kernel.org/r/ad66e0a0ad96feb848814842ecf5b6a4539ef35c.1605121038.git.lukas@wunner.de Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 5e844cc commit e1483ac

1 file changed

Lines changed: 8 additions & 16 deletions

File tree

drivers/spi/spi-bcm2835.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
12781278
struct bcm2835_spi *bs;
12791279
int err;
12801280

1281-
ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
1281+
ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
12821282
dma_get_cache_alignment()));
12831283
if (!ctlr)
12841284
return -ENOMEM;
@@ -1299,23 +1299,17 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
12991299
bs->ctlr = ctlr;
13001300

13011301
bs->regs = devm_platform_ioremap_resource(pdev, 0);
1302-
if (IS_ERR(bs->regs)) {
1303-
err = PTR_ERR(bs->regs);
1304-
goto out_controller_put;
1305-
}
1302+
if (IS_ERR(bs->regs))
1303+
return PTR_ERR(bs->regs);
13061304

13071305
bs->clk = devm_clk_get(&pdev->dev, NULL);
1308-
if (IS_ERR(bs->clk)) {
1309-
err = dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
1310-
"could not get clk\n");
1311-
goto out_controller_put;
1312-
}
1306+
if (IS_ERR(bs->clk))
1307+
return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
1308+
"could not get clk\n");
13131309

13141310
bs->irq = platform_get_irq(pdev, 0);
1315-
if (bs->irq <= 0) {
1316-
err = bs->irq ? bs->irq : -ENODEV;
1317-
goto out_controller_put;
1318-
}
1311+
if (bs->irq <= 0)
1312+
return bs->irq ? bs->irq : -ENODEV;
13191313

13201314
clk_prepare_enable(bs->clk);
13211315

@@ -1349,8 +1343,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
13491343
bcm2835_dma_release(ctlr, bs);
13501344
out_clk_disable:
13511345
clk_disable_unprepare(bs->clk);
1352-
out_controller_put:
1353-
spi_controller_put(ctlr);
13541346
return err;
13551347
}
13561348

0 commit comments

Comments
 (0)