CVE-2026-45996
Description
In the Linux kernel, the following vulnerability has been resolved:
spi: imx: fix use-after-free on unbind
The SPI subsystem frees the controller and any subsystem allocated driver data as part of deregistration (unless the allocation is device managed).
Take another reference before deregistering the controller so that the driver data is not freed until the driver is done with it.
Affected products
1Patches
10aa9025a49803spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
385a330083f8spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 94d0f7695d07a3..6779ebdec94c31 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1893,6 +1893,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1906,6 +1908,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 94d0f7695d07a3..6779ebdec94c31 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1893,6 +1893,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1906,6 +1908,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
f99165ef0677spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 76f8747c294326..c8caf60b36dab9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1898,6 +1898,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1911,6 +1913,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int __maybe_unused spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 76f8747c294326..c8caf60b36dab9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1898,6 +1898,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1911,6 +1913,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int __maybe_unused spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
132e47030b0bspi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index bbf1fd4fe1e925..dc7ffa8cb2878a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1965,6 +1965,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1978,6 +1980,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index bbf1fd4fe1e925..dc7ffa8cb2878a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1965,6 +1965,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1978,6 +1980,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
1c78c2002380spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
1c78c2002380spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
f99165ef0677spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 76f8747c294326..c8caf60b36dab9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1898,6 +1898,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1911,6 +1913,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int __maybe_unused spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 76f8747c294326..c8caf60b36dab9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1898,6 +1898,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1911,6 +1913,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int __maybe_unused spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
aa9025a49803spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7bff..a8d90c86a8a11d 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
132e47030b0bspi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index bbf1fd4fe1e925..dc7ffa8cb2878a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1965,6 +1965,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1978,6 +1980,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index bbf1fd4fe1e925..dc7ffa8cb2878a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1965,6 +1965,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1978,6 +1980,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
385a330083f8spi: imx: fix use-after-free on unbind
2 files changed · +8 −2
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 94d0f7695d07a3..6779ebdec94c31 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1893,6 +1893,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1906,6 +1908,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
drivers/spi/spi-imx.c+4 −1 modifieddiff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 94d0f7695d07a3..6779ebdec94c31 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1893,6 +1893,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -1906,6 +1908,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Use-after-free in spi_imx_remove() where driver data is accessed after spi_unregister_controller() frees it."
Attack vector
An attacker with the ability to unbind the SPI IMX driver (e.g., via sysfs device unbind or driver removal) triggers the `spi_imx_remove()` callback. The SPI subsystem frees the controller and its driver data during `spi_unregister_controller()`, but the driver continues to access the freed `spi_imx` structure for `pm_runtime_get_sync()`, `pm_runtime_disable()`, and `spi_imx_sdma_exit()`. This use-after-free can lead to memory corruption or a kernel crash.
Affected code
The vulnerability is in the `spi_imx_remove()` function in `drivers/spi/spi-imx.c` [patch_id=2660596]. The function calls `spi_unregister_controller()` which frees the controller and its driver data, then continues to access `spi_imx` (obtained via `spi_controller_get_devdata()`) for runtime PM operations and SDMA cleanup.
What the fix does
The patch adds a `spi_controller_get(controller)` call before `spi_unregister_controller()` to take an extra reference on the controller, preventing the SPI subsystem from freeing the controller and its driver data during deregistration. After all cleanup operations (runtime PM disable, SDMA exit) are complete, `spi_controller_put(controller)` releases the extra reference, allowing the controller to be freed safely. This ensures the driver data remains valid for the entire remove sequence.
Preconditions
- authAttacker must be able to trigger unbind of the spi-imx driver (e.g., via sysfs 'unbind' or driver module removal)
- configThe SPI controller must not be device-managed (non-devm allocation)
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/132e47030b0b5e398e0da6c59df5a5dae9b52cffnvd
- git.kernel.org/stable/c/1c78c2002380a1fe31bfb01a3d5f29809e55a096nvd
- git.kernel.org/stable/c/385a330083f8dd47c15b02e9a83aef9234a37003nvd
- git.kernel.org/stable/c/aa9025a498036b6012769f7af36d421385386c17nvd
- git.kernel.org/stable/c/f99165ef067723221472ce1aff632bc74f562643nvd
News mentions
0No linked articles in our index yet.