Skip to content

Commit c371dcf

Browse files
committed
Merge series "Use-after-free be gone" from Lukas Wunner <lukas@wunner.de>:
Here's my proposal to fix the use-after-free bugs reported by Sascha Hauer and Florian Fainelli: I scrutinized all SPI drivers in the v5.10 tree: * There are 9 drivers with a use-after-free in the ->remove() hook caused by accessing driver private data after spi_unregister_controller(). * There are 8 drivers which leak the spi_controller in the ->probe() error path because of a missing spi_controller_put(). I'm introducing devm_spi_alloc_master/slave() which automatically calls spi_controller_put() on ->remove(). This fixes both classes of bugs while at the same time reducing code amount and complexity in the ->probe() hook. I propose that spi_controller_unregister() should no longer release a reference on the spi_controller. Instead, drivers need to either do it themselves or use one of the devm functions introduced herein. The vast majority of drivers can be converted to the devm functions. See the commit message of patch [1/4] for the rationale and details. Enclosed are patches for 3 Broadcom drivers. Patches for the other drivers are on this branch: https://github.com/l1k/linux/commits/spi_fixes @florian Fainelli: Could you verify that there are no KASAN splats or leaks with these patches? Unfortunately I do not have any SPI-capable hardware at my disposal right now, so can only compile-test. You may want to augment spi_controller_release() with a printk() to log when the spi_controller is freed. @mark Brown: Patches [2/4] to [4/4] reference the SHA-1 of patch [1/4] in their stable tags. Because the hash is unknown to me until you apply the patch, I've used "123456789abc" as a placeholder. You'll have to replace the hash if/when applying. Alternatively, only apply patch [1/4] and I'll repost the other patches with the hash fixed up. Thanks! Lukas Wunner (4): spi: Introduce device-managed SPI controller allocation spi: bcm2835: Fix use-after-free on unbind spi: bcm2835aux: Fix use-after-free on unbind spi: bcm-qspi: Fix use-after-free on unbind drivers/spi/spi-bcm-qspi.c | 34 ++++++++------------- drivers/spi/spi-bcm2835.c | 24 +++++---------- drivers/spi/spi-bcm2835aux.c | 21 +++++-------- drivers/spi/spi.c | 58 +++++++++++++++++++++++++++++++++++- include/linux/spi/spi.h | 19 ++++++++++++ 5 files changed, 103 insertions(+), 53 deletions(-) -- 2.28.0
2 parents 4def49d + 63c5395 commit c371dcf

5 files changed

Lines changed: 103 additions & 53 deletions

File tree

drivers/spi/spi-bcm-qspi.c

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
13271327

13281328
data = of_id->data;
13291329

1330-
master = spi_alloc_master(dev, sizeof(struct bcm_qspi));
1330+
master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi));
13311331
if (!master) {
13321332
dev_err(dev, "error allocating spi_master\n");
13331333
return -ENOMEM;
@@ -1367,21 +1367,17 @@ int bcm_qspi_probe(struct platform_device *pdev,
13671367

13681368
if (res) {
13691369
qspi->base[MSPI] = devm_ioremap_resource(dev, res);
1370-
if (IS_ERR(qspi->base[MSPI])) {
1371-
ret = PTR_ERR(qspi->base[MSPI]);
1372-
goto qspi_resource_err;
1373-
}
1370+
if (IS_ERR(qspi->base[MSPI]))
1371+
return PTR_ERR(qspi->base[MSPI]);
13741372
} else {
1375-
goto qspi_resource_err;
1373+
return 0;
13761374
}
13771375

13781376
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
13791377
if (res) {
13801378
qspi->base[BSPI] = devm_ioremap_resource(dev, res);
1381-
if (IS_ERR(qspi->base[BSPI])) {
1382-
ret = PTR_ERR(qspi->base[BSPI]);
1383-
goto qspi_resource_err;
1384-
}
1379+
if (IS_ERR(qspi->base[BSPI]))
1380+
return PTR_ERR(qspi->base[BSPI]);
13851381
qspi->bspi_mode = true;
13861382
} else {
13871383
qspi->bspi_mode = false;
@@ -1392,18 +1388,14 @@ int bcm_qspi_probe(struct platform_device *pdev,
13921388
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg");
13931389
if (res) {
13941390
qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res);
1395-
if (IS_ERR(qspi->base[CHIP_SELECT])) {
1396-
ret = PTR_ERR(qspi->base[CHIP_SELECT]);
1397-
goto qspi_resource_err;
1398-
}
1391+
if (IS_ERR(qspi->base[CHIP_SELECT]))
1392+
return PTR_ERR(qspi->base[CHIP_SELECT]);
13991393
}
14001394

14011395
qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id),
14021396
GFP_KERNEL);
1403-
if (!qspi->dev_ids) {
1404-
ret = -ENOMEM;
1405-
goto qspi_resource_err;
1406-
}
1397+
if (!qspi->dev_ids)
1398+
return -ENOMEM;
14071399

14081400
for (val = 0; val < num_irqs; val++) {
14091401
irq = -1;
@@ -1484,7 +1476,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
14841476
qspi->xfer_mode.addrlen = -1;
14851477
qspi->xfer_mode.hp = -1;
14861478

1487-
ret = devm_spi_register_master(&pdev->dev, master);
1479+
ret = spi_register_master(master);
14881480
if (ret < 0) {
14891481
dev_err(dev, "can't register master\n");
14901482
goto qspi_reg_err;
@@ -1497,8 +1489,6 @@ int bcm_qspi_probe(struct platform_device *pdev,
14971489
clk_disable_unprepare(qspi->clk);
14981490
qspi_probe_err:
14991491
kfree(qspi->dev_ids);
1500-
qspi_resource_err:
1501-
spi_master_put(master);
15021492
return ret;
15031493
}
15041494
/* probe function to be called by SoC specific platform driver probe */
@@ -1508,10 +1498,10 @@ int bcm_qspi_remove(struct platform_device *pdev)
15081498
{
15091499
struct bcm_qspi *qspi = platform_get_drvdata(pdev);
15101500

1501+
spi_unregister_master(qspi->master);
15111502
bcm_qspi_hw_uninit(qspi);
15121503
clk_disable_unprepare(qspi->clk);
15131504
kfree(qspi->dev_ids);
1514-
spi_unregister_master(qspi->master);
15151505

15161506
return 0;
15171507
}

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

drivers/spi/spi-bcm2835aux.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
494494
unsigned long clk_hz;
495495
int err;
496496

497-
master = spi_alloc_master(&pdev->dev, sizeof(*bs));
497+
master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
498498
if (!master)
499499
return -ENOMEM;
500500

@@ -524,29 +524,24 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
524524

525525
/* the main area */
526526
bs->regs = devm_platform_ioremap_resource(pdev, 0);
527-
if (IS_ERR(bs->regs)) {
528-
err = PTR_ERR(bs->regs);
529-
goto out_master_put;
530-
}
527+
if (IS_ERR(bs->regs))
528+
return PTR_ERR(bs->regs);
531529

532530
bs->clk = devm_clk_get(&pdev->dev, NULL);
533531
if (IS_ERR(bs->clk)) {
534-
err = PTR_ERR(bs->clk);
535532
dev_err(&pdev->dev, "could not get clk: %d\n", err);
536-
goto out_master_put;
533+
return PTR_ERR(bs->clk);
537534
}
538535

539536
bs->irq = platform_get_irq(pdev, 0);
540-
if (bs->irq <= 0) {
541-
err = bs->irq ? bs->irq : -ENODEV;
542-
goto out_master_put;
543-
}
537+
if (bs->irq <= 0)
538+
return bs->irq ? bs->irq : -ENODEV;
544539

545540
/* this also enables the HW block */
546541
err = clk_prepare_enable(bs->clk);
547542
if (err) {
548543
dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
549-
goto out_master_put;
544+
return err;
550545
}
551546

552547
/* just checking if the clock returns a sane value */
@@ -581,8 +576,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
581576

582577
out_clk_disable:
583578
clk_disable_unprepare(bs->clk);
584-
out_master_put:
585-
spi_master_put(master);
586579
return err;
587580
}
588581

drivers/spi/spi.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2442,6 +2442,49 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
24422442
}
24432443
EXPORT_SYMBOL_GPL(__spi_alloc_controller);
24442444

2445+
static void devm_spi_release_controller(struct device *dev, void *ctlr)
2446+
{
2447+
spi_controller_put(*(struct spi_controller **)ctlr);
2448+
}
2449+
2450+
/**
2451+
* __devm_spi_alloc_controller - resource-managed __spi_alloc_controller()
2452+
* @dev: physical device of SPI controller
2453+
* @size: how much zeroed driver-private data to allocate
2454+
* @slave: whether to allocate an SPI master (false) or SPI slave (true)
2455+
* Context: can sleep
2456+
*
2457+
* Allocate an SPI controller and automatically release a reference on it
2458+
* when @dev is unbound from its driver. Drivers are thus relieved from
2459+
* having to call spi_controller_put().
2460+
*
2461+
* The arguments to this function are identical to __spi_alloc_controller().
2462+
*
2463+
* Return: the SPI controller structure on success, else NULL.
2464+
*/
2465+
struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
2466+
unsigned int size,
2467+
bool slave)
2468+
{
2469+
struct spi_controller **ptr, *ctlr;
2470+
2471+
ptr = devres_alloc(devm_spi_release_controller, sizeof(*ptr),
2472+
GFP_KERNEL);
2473+
if (!ptr)
2474+
return NULL;
2475+
2476+
ctlr = __spi_alloc_controller(dev, size, slave);
2477+
if (ctlr) {
2478+
*ptr = ctlr;
2479+
devres_add(dev, ptr);
2480+
} else {
2481+
devres_free(ptr);
2482+
}
2483+
2484+
return ctlr;
2485+
}
2486+
EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller);
2487+
24452488
#ifdef CONFIG_OF
24462489
static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
24472490
{
@@ -2778,6 +2821,11 @@ int devm_spi_register_controller(struct device *dev,
27782821
}
27792822
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
27802823

2824+
static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr)
2825+
{
2826+
return *(struct spi_controller **)res == ctlr;
2827+
}
2828+
27812829
static int __unregister(struct device *dev, void *null)
27822830
{
27832831
spi_unregister_device(to_spi_device(dev));
@@ -2819,7 +2867,15 @@ void spi_unregister_controller(struct spi_controller *ctlr)
28192867
list_del(&ctlr->list);
28202868
mutex_unlock(&board_lock);
28212869

2822-
device_unregister(&ctlr->dev);
2870+
device_del(&ctlr->dev);
2871+
2872+
/* Release the last reference on the controller if its driver
2873+
* has not yet been converted to devm_spi_alloc_master/slave().
2874+
*/
2875+
if (!devres_find(ctlr->dev.parent, devm_spi_release_controller,
2876+
devm_spi_match_controller, ctlr))
2877+
put_device(&ctlr->dev);
2878+
28232879
/* free bus id */
28242880
mutex_lock(&board_lock);
28252881
if (found == ctlr)

include/linux/spi/spi.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,25 @@ static inline struct spi_controller *spi_alloc_slave(struct device *host,
734734
return __spi_alloc_controller(host, size, true);
735735
}
736736

737+
struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
738+
unsigned int size,
739+
bool slave);
740+
741+
static inline struct spi_controller *devm_spi_alloc_master(struct device *dev,
742+
unsigned int size)
743+
{
744+
return __devm_spi_alloc_controller(dev, size, false);
745+
}
746+
747+
static inline struct spi_controller *devm_spi_alloc_slave(struct device *dev,
748+
unsigned int size)
749+
{
750+
if (!IS_ENABLED(CONFIG_SPI_SLAVE))
751+
return NULL;
752+
753+
return __devm_spi_alloc_controller(dev, size, true);
754+
}
755+
737756
extern int spi_register_controller(struct spi_controller *ctlr);
738757
extern int devm_spi_register_controller(struct device *dev,
739758
struct spi_controller *ctlr);

0 commit comments

Comments
 (0)