Skip to content

Commit 335c901

Browse files
committed
Merge tag 'spi-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "There are two core fixes here. One is from Johan dealing with an issue introduced by a devm_ API usage update causing things to be freed earlier than they had earlier when we fail to register a device, another from Danilo avoids unlocked acccess to data by converting to use a driver core API. We also have a few relatively minor driver specific fixes" * tag 'spi-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi-fsl-lpspi: fix teardown order issue (UAF) spi: fix use-after-free on managed registration failure spi: use generic driver_override infrastructure spi: meson-spicc: Fix double-put in remove path spi: sn-f-ospi: Use devm_mutex_init() to simplify code spi: sn-f-ospi: Fix resource leak in f_ospi_probe()
2 parents cd0bbd5 + b341c11 commit 335c901

5 files changed

Lines changed: 31 additions & 53 deletions

File tree

drivers/spi/spi-fsl-lpspi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
10091009
enable_irq(irq);
10101010
}
10111011

1012-
ret = devm_spi_register_controller(&pdev->dev, controller);
1012+
ret = spi_register_controller(controller);
10131013
if (ret < 0) {
10141014
dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
10151015
goto free_dma;
@@ -1035,6 +1035,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
10351035
struct fsl_lpspi_data *fsl_lpspi =
10361036
spi_controller_get_devdata(controller);
10371037

1038+
spi_unregister_controller(controller);
10381039
fsl_lpspi_dma_exit(controller);
10391040

10401041
pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);

drivers/spi/spi-meson-spicc.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,6 @@ static void meson_spicc_remove(struct platform_device *pdev)
11011101

11021102
/* Disable SPI */
11031103
writel(0, spicc->base + SPICC_CONREG);
1104-
1105-
spi_controller_put(spicc->host);
11061104
}
11071105

11081106
static const struct meson_spicc_data meson_spicc_gx_data = {

drivers/spi/spi-sn-f-ospi.c

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ static int f_ospi_probe(struct platform_device *pdev)
612612
u32 num_cs = OSPI_NUM_CS;
613613
int ret;
614614

615-
ctlr = spi_alloc_host(dev, sizeof(*ospi));
615+
ctlr = devm_spi_alloc_host(dev, sizeof(*ospi));
616616
if (!ctlr)
617617
return -ENOMEM;
618618

@@ -635,43 +635,22 @@ static int f_ospi_probe(struct platform_device *pdev)
635635
platform_set_drvdata(pdev, ospi);
636636

637637
ospi->base = devm_platform_ioremap_resource(pdev, 0);
638-
if (IS_ERR(ospi->base)) {
639-
ret = PTR_ERR(ospi->base);
640-
goto err_put_ctlr;
641-
}
638+
if (IS_ERR(ospi->base))
639+
return PTR_ERR(ospi->base);
642640

643641
ospi->clk = devm_clk_get_enabled(dev, NULL);
644-
if (IS_ERR(ospi->clk)) {
645-
ret = PTR_ERR(ospi->clk);
646-
goto err_put_ctlr;
647-
}
642+
if (IS_ERR(ospi->clk))
643+
return PTR_ERR(ospi->clk);
648644

649-
mutex_init(&ospi->mlock);
650-
651-
ret = f_ospi_init(ospi);
645+
ret = devm_mutex_init(dev, &ospi->mlock);
652646
if (ret)
653-
goto err_destroy_mutex;
647+
return ret;
654648

655-
ret = devm_spi_register_controller(dev, ctlr);
649+
ret = f_ospi_init(ospi);
656650
if (ret)
657-
goto err_destroy_mutex;
658-
659-
return 0;
660-
661-
err_destroy_mutex:
662-
mutex_destroy(&ospi->mlock);
663-
664-
err_put_ctlr:
665-
spi_controller_put(ctlr);
666-
667-
return ret;
668-
}
669-
670-
static void f_ospi_remove(struct platform_device *pdev)
671-
{
672-
struct f_ospi *ospi = platform_get_drvdata(pdev);
651+
return ret;
673652

674-
mutex_destroy(&ospi->mlock);
653+
return devm_spi_register_controller(dev, ctlr);
675654
}
676655

677656
static const struct of_device_id f_ospi_dt_ids[] = {
@@ -686,7 +665,6 @@ static struct platform_driver f_ospi_driver = {
686665
.of_match_table = f_ospi_dt_ids,
687666
},
688667
.probe = f_ospi_probe,
689-
.remove = f_ospi_remove,
690668
};
691669
module_platform_driver(f_ospi_driver);
692670

drivers/spi/spi.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ static void spidev_release(struct device *dev)
5050
struct spi_device *spi = to_spi_device(dev);
5151

5252
spi_controller_put(spi->controller);
53-
kfree(spi->driver_override);
5453
free_percpu(spi->pcpu_statistics);
5554
kfree(spi);
5655
}
@@ -73,10 +72,9 @@ static ssize_t driver_override_store(struct device *dev,
7372
struct device_attribute *a,
7473
const char *buf, size_t count)
7574
{
76-
struct spi_device *spi = to_spi_device(dev);
7775
int ret;
7876

79-
ret = driver_set_override(dev, &spi->driver_override, buf, count);
77+
ret = __device_set_driver_override(dev, buf, count);
8078
if (ret)
8179
return ret;
8280

@@ -86,13 +84,8 @@ static ssize_t driver_override_store(struct device *dev,
8684
static ssize_t driver_override_show(struct device *dev,
8785
struct device_attribute *a, char *buf)
8886
{
89-
const struct spi_device *spi = to_spi_device(dev);
90-
ssize_t len;
91-
92-
device_lock(dev);
93-
len = sysfs_emit(buf, "%s\n", spi->driver_override ? : "");
94-
device_unlock(dev);
95-
return len;
87+
guard(spinlock)(&dev->driver_override.lock);
88+
return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: "");
9689
}
9790
static DEVICE_ATTR_RW(driver_override);
9891

@@ -376,10 +369,12 @@ static int spi_match_device(struct device *dev, const struct device_driver *drv)
376369
{
377370
const struct spi_device *spi = to_spi_device(dev);
378371
const struct spi_driver *sdrv = to_spi_driver(drv);
372+
int ret;
379373

380374
/* Check override first, and if set, only use the named driver */
381-
if (spi->driver_override)
382-
return strcmp(spi->driver_override, drv->name) == 0;
375+
ret = device_match_driver_override(dev, drv);
376+
if (ret >= 0)
377+
return ret;
383378

384379
/* Attempt an OF style match */
385380
if (of_driver_match_device(dev, drv))
@@ -3539,8 +3534,19 @@ int devm_spi_register_controller(struct device *dev,
35393534
if (ret)
35403535
return ret;
35413536

3542-
return devm_add_action_or_reset(dev, devm_spi_unregister_controller, ctlr);
3537+
/*
3538+
* Prevent controller from being freed by spi_unregister_controller()
3539+
* if devm_add_action_or_reset() fails for a non-devres allocated
3540+
* controller.
3541+
*/
3542+
spi_controller_get(ctlr);
3543+
3544+
ret = devm_add_action_or_reset(dev, devm_spi_unregister_controller, ctlr);
35433545

3546+
if (ret == 0 || ctlr->devm_allocated)
3547+
spi_controller_put(ctlr);
3548+
3549+
return ret;
35443550
}
35453551
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
35463552

include/linux/spi/spi.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
159159
* @modalias: Name of the driver to use with this device, or an alias
160160
* for that name. This appears in the sysfs "modalias" attribute
161161
* for driver coldplugging, and in uevents used for hotplugging
162-
* @driver_override: If the name of a driver is written to this attribute, then
163-
* the device will bind to the named driver and only the named driver.
164-
* Do not set directly, because core frees it; use driver_set_override() to
165-
* set or clear it.
166162
* @pcpu_statistics: statistics for the spi_device
167163
* @word_delay: delay to be inserted between consecutive
168164
* words of a transfer
@@ -224,7 +220,6 @@ struct spi_device {
224220
void *controller_state;
225221
void *controller_data;
226222
char modalias[SPI_NAME_SIZE];
227-
const char *driver_override;
228223

229224
/* The statistics */
230225
struct spi_statistics __percpu *pcpu_statistics;

0 commit comments

Comments
 (0)