From: Greg Kroah-Hartman Date: Tue, 24 Nov 2020 18:05:02 +0000 (+0100) Subject: 5.9-stable patches X-Git-Tag: v4.4.247~57 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=552a4436e315281b6dd2dacac10c206e0042aa86;p=thirdparty%2Fkernel%2Fstable-queue.git 5.9-stable patches added patches: spi-bcm-qspi-fix-use-after-free-on-unbind.patch --- diff --git a/queue-5.9/series b/queue-5.9/series index a3ac43debf7..bea91a17c40 100644 --- a/queue-5.9/series +++ b/queue-5.9/series @@ -1,2 +1,3 @@ io_uring-get-an-active-ref_node-from-files_data.patch io_uring-order-refnode-recycling.patch +spi-bcm-qspi-fix-use-after-free-on-unbind.patch diff --git a/queue-5.9/spi-bcm-qspi-fix-use-after-free-on-unbind.patch b/queue-5.9/spi-bcm-qspi-fix-use-after-free-on-unbind.patch new file mode 100644 index 00000000000..7f9c7d40791 --- /dev/null +++ b/queue-5.9/spi-bcm-qspi-fix-use-after-free-on-unbind.patch @@ -0,0 +1,133 @@ +From foo@baz Tue Nov 24 07:04:37 PM CET 2020 +From: Lukas Wunner +Date: Wed, 11 Nov 2020 20:07:40 +0100 +Subject: spi: bcm-qspi: Fix use-after-free on unbind + +From: Lukas Wunner + +commit 63c5395bb7a9777a33f0e7b5906f2c0170a23692 upstream + +bcm_qspi_remove() calls spi_unregister_master() even though +bcm_qspi_probe() calls devm_spi_register_master(). The spi_master is +therefore unregistered and freed twice on unbind. + +Moreover, since commit 0392727c261b ("spi: bcm-qspi: Handle clock probe +deferral"), bcm_qspi_probe() leaks the spi_master allocation if the call +to devm_clk_get_optional() fails. + +Fix by switching over to the new devm_spi_alloc_master() helper which +keeps the private data accessible until the driver has unbound and also +avoids the spi_master leak on probe. + +While at it, fix an ordering issue in bcm_qspi_remove() wherein +spi_unregister_master() is called after uninitializing the hardware, +disabling the clock and freeing an IRQ data structure. The correct +order is to call spi_unregister_master() *before* those teardown steps +because bus accesses may still be ongoing until that function returns. + +Fixes: fa236a7ef240 ("spi: bcm-qspi: Add Broadcom MSPI driver") +Signed-off-by: Lukas Wunner +Cc: # v4.9+: 123456789abc: spi: Introduce device-managed SPI controller allocation +Cc: # v4.9+ +Cc: Kamal Dasu +Acked-by: Florian Fainelli +Tested-by: Florian Fainelli +Link: https://lore.kernel.org/r/5e31a9a59fd1c0d0b795b2fe219f25e5ee855f9d.1605121038.git.lukas@wunner.de +Signed-off-by: Mark Brown +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-bcm-qspi.c | 34 ++++++++++++---------------------- + 1 file changed, 12 insertions(+), 22 deletions(-) + +--- a/drivers/spi/spi-bcm-qspi.c ++++ b/drivers/spi/spi-bcm-qspi.c +@@ -1334,7 +1334,7 @@ int bcm_qspi_probe(struct platform_devic + + data = of_id->data; + +- master = spi_alloc_master(dev, sizeof(struct bcm_qspi)); ++ master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi)); + if (!master) { + dev_err(dev, "error allocating spi_master\n"); + return -ENOMEM; +@@ -1374,21 +1374,17 @@ int bcm_qspi_probe(struct platform_devic + + if (res) { + qspi->base[MSPI] = devm_ioremap_resource(dev, res); +- if (IS_ERR(qspi->base[MSPI])) { +- ret = PTR_ERR(qspi->base[MSPI]); +- goto qspi_resource_err; +- } ++ if (IS_ERR(qspi->base[MSPI])) ++ return PTR_ERR(qspi->base[MSPI]); + } else { +- goto qspi_resource_err; ++ return 0; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); + if (res) { + qspi->base[BSPI] = devm_ioremap_resource(dev, res); +- if (IS_ERR(qspi->base[BSPI])) { +- ret = PTR_ERR(qspi->base[BSPI]); +- goto qspi_resource_err; +- } ++ if (IS_ERR(qspi->base[BSPI])) ++ return PTR_ERR(qspi->base[BSPI]); + qspi->bspi_mode = true; + } else { + qspi->bspi_mode = false; +@@ -1399,18 +1395,14 @@ int bcm_qspi_probe(struct platform_devic + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg"); + if (res) { + qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); +- if (IS_ERR(qspi->base[CHIP_SELECT])) { +- ret = PTR_ERR(qspi->base[CHIP_SELECT]); +- goto qspi_resource_err; +- } ++ if (IS_ERR(qspi->base[CHIP_SELECT])) ++ return PTR_ERR(qspi->base[CHIP_SELECT]); + } + + qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id), + GFP_KERNEL); +- if (!qspi->dev_ids) { +- ret = -ENOMEM; +- goto qspi_resource_err; +- } ++ if (!qspi->dev_ids) ++ return -ENOMEM; + + for (val = 0; val < num_irqs; val++) { + irq = -1; +@@ -1491,7 +1483,7 @@ int bcm_qspi_probe(struct platform_devic + qspi->xfer_mode.addrlen = -1; + qspi->xfer_mode.hp = -1; + +- ret = devm_spi_register_master(&pdev->dev, master); ++ ret = spi_register_master(master); + if (ret < 0) { + dev_err(dev, "can't register master\n"); + goto qspi_reg_err; +@@ -1504,8 +1496,6 @@ qspi_reg_err: + clk_disable_unprepare(qspi->clk); + qspi_probe_err: + kfree(qspi->dev_ids); +-qspi_resource_err: +- spi_master_put(master); + return ret; + } + /* probe function to be called by SoC specific platform driver probe */ +@@ -1515,10 +1505,10 @@ int bcm_qspi_remove(struct platform_devi + { + struct bcm_qspi *qspi = platform_get_drvdata(pdev); + ++ spi_unregister_master(qspi->master); + bcm_qspi_hw_uninit(qspi); + clk_disable_unprepare(qspi->clk); + kfree(qspi->dev_ids); +- spi_unregister_master(qspi->master); + + return 0; + }