CVE-2026-46225
Description
In the Linux kernel, the following vulnerability has been resolved:
spi: rspi: fix controller deregistration
Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel spi-rspi driver fails to deregister SPI controller before releasing DMA resources, causing use-after-free on unbind.
Vulnerability
In the Linux kernel's SPI RSPI driver (drivers/spi/spi-rspi.c), the controller deregistration is performed after releasing underlying resources such as DMA during driver unbind. This creates a use-after-free condition. The bug affects all kernel versions up to and including the commit prior to the fix [1].
Exploitation
An attacker would need the ability to trigger a driver unbind operation (e.g., via device removal or forced unbind) while the SPI controller is active. No special privileges beyond local access are required; the race window occurs during the unbind sequence.
Impact
Successful exploitation leads to a use-after-free on a SPI controller structure, which could result in system crash (denial of service) or potentially privilege escalation depending on the memory state. The vulnerability is classified as a bug fix, not explicitly proven exploitable for code execution [1].
Mitigation
The fix was applied in Linux kernel commit 77defd64b405b680db73d767313fce770d368368 [1]. Users should update to a kernel version containing this commit. No workaround is available; the driver should be compiled as a module only if immediate unbind is not required.
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
1077defd64b405spi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8e81f1a8623f90..3a4f9a276cf56f 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1176,8 +1176,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1387,9 +1393,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
aee76c1dd189spi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8e1d911b88b51c..c90dfe5211542b 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1377,9 +1383,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
fee6abd9845cspi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index c739c1998b4ce6..a8180dece716f3 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
9944fa6726afspi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index c739c1998b4ce6..a8180dece716f3 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
c5090db1b31dspi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 7f95d22fb1ac65..77809e3a5dba7d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1377,9 +1383,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
fee6abd9845cspi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index c739c1998b4ce6..a8180dece716f3 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
9944fa6726afspi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index c739c1998b4ce6..a8180dece716f3 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
c5090db1b31dspi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 7f95d22fb1ac65..77809e3a5dba7d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1377,9 +1383,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
77defd64b405spi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8e81f1a8623f90..3a4f9a276cf56f 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1176,8 +1176,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1387,9 +1393,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
aee76c1dd189spi: rspi: fix controller deregistration
1 file changed · +8 −3
drivers/spi/spi-rspi.c+8 −3 modifieddiff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8e1d911b88b51c..c90dfe5211542b 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1377,9 +1383,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Incorrect teardown ordering in rspi_remove: DMA and runtime PM resources are released before the SPI controller is unregistered, and the probe function used devm-spi-register which prevented explicit ordering control."
Attack vector
An attacker triggers the bug by causing the SPI RSPI driver to unbind (e.g., via driver removal or device hot-unplug) while the SPI controller is still registered and potentially active. During `rspi_remove`, DMA resources are released before the controller is unregistered, which can lead to use-after-free or other memory corruption if the SPI framework or any child device attempts to access the freed DMA resources through the still-registered controller. No special network path or authentication is required; the precondition is that the driver is bound and then removed.
Affected code
The vulnerability is in the `rspi_remove` function and `rspi_probe` function within `drivers/spi/spi-rspi.c` [patch_id=2897623]. The `rspi_remove` function called `rspi_release_dma()` and `pm_runtime_disable()` before calling `spi_unregister_controller()`, and the probe function used `devm_spi_register_controller()` which tied controller deregistration to device resource release rather than explicit ordering.
What the fix does
The patch reorders operations in `rspi_remove` so that `spi_unregister_controller()` is called before `rspi_release_dma()` and `pm_runtime_disable()`, ensuring the controller is fully deregistered before its underlying resources are freed [patch_id=2897623]. It also adds `spi_controller_get()`/`spi_controller_put()` around the unregister call to prevent the controller from being freed prematurely. In `rspi_probe`, the patch replaces `devm_spi_register_controller()` with `spi_register_controller()`, removing the automatic device-managed deregistration so that the driver explicitly controls the order of teardown.
Preconditions
- configThe SPI RSPI driver must be bound to a device and then removed (driver unbind or device hot-unplug).
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/77defd64b405b680db73d767313fce770d368368nvd
- git.kernel.org/stable/c/9944fa6726afb1e6eb7e2212764e7da0c97f2dccnvd
- git.kernel.org/stable/c/aee76c1dd189562c6678313caec12761f78a9ef3nvd
- git.kernel.org/stable/c/c5090db1b31de3ef4db0cda7e822ab49cb572292nvd
- git.kernel.org/stable/c/fee6abd9845c3edd217b0e429d09f764f9a5690envd
News mentions
0No linked articles in our index yet.