CVE-2026-46301
Description
Linux kernel spi: topcliff-pch driver has a use-after-free vulnerability on unbind, potentially leading to system instability.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel spi: topcliff-pch driver has a use-after-free vulnerability on unbind, potentially leading to system instability.
Vulnerability
A use-after-free vulnerability exists in the spi: topcliff-pch driver within the Linux kernel. This issue occurs during the driver unbind process, specifically when DMA buffers are released before the driver has a chance to flush its queue.
Exploitation
An attacker would need to trigger the driver unbind operation while the driver is still actively using DMA buffers. This could potentially be achieved through specific hardware interactions or by manipulating the driver's lifecycle within the kernel, though details on precise exploitation steps are not provided.
Impact
Successful exploitation of this use-after-free vulnerability could lead to system instability, crashes, or potentially allow for arbitrary code execution with kernel privileges, depending on the exact state of the system and memory corruption.
Mitigation
This vulnerability has been resolved in the Linux kernel. The fix involves ensuring the driver flushes its queue before releasing DMA buffers on driver unbind. Specific patched kernel versions are not detailed in the available references, but the fix is available in the stable kernel tree [1].
AI Insight generated on Jun 8, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
160e8e57f9737espi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index c120436434d0e..14d11450e86dc 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
4ca90deeca1cspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index cbb60198a7f00..3ab3b25449064 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1406,9 +1406,6 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1432,6 +1429,9 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); -- cgit 1.3-korg
d79e92161b65spi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index af5846cfe5e91..f34603df0114d 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1406,9 +1406,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1432,6 +1429,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); } -- cgit 1.3-korg
43334836b907spi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 7fb020a1d66aa..26e2d355bd199 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1426,9 +1426,6 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1452,6 +1449,9 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); -- cgit 1.3-korg
8822980668c9spi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 1a85b92e9eaa3..4580b294e9373 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
9d72732fe70cspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index c120436434d0e..14d11450e86dc 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
36e58c436d2cspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 8c4615b763398..cd2af4c0ba1d3 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1427,9 +1427,6 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1453,6 +1450,9 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); -- cgit 1.3-korg
d50ef3553acbspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 77527a4371839..87de0145f35fe 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
0e8e57f9737espi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index c120436434d0e..14d11450e86dc 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
36e58c436d2cspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 8c4615b763398..cd2af4c0ba1d3 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1427,9 +1427,6 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1453,6 +1450,9 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); -- cgit 1.3-korg
43334836b907spi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 7fb020a1d66aa..26e2d355bd199 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1426,9 +1426,6 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1452,6 +1449,9 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); -- cgit 1.3-korg
d79e92161b65spi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index af5846cfe5e91..f34603df0114d 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1406,9 +1406,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1432,6 +1429,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); } -- cgit 1.3-korg
4ca90deeca1cspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index cbb60198a7f00..3ab3b25449064 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1406,9 +1406,6 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", __func__, plat_dev->id, board_dat->pdev->irq); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1432,6 +1429,9 @@ static int pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_unregister_master(data->master); -- cgit 1.3-korg
d50ef3553acbspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 77527a4371839..87de0145f35fe 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
9d72732fe70cspi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index c120436434d0e..14d11450e86dc 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
8822980668c9spi: topcliff-pch: fix use-after-free on unbind
1 file changed · +3 −4
drivers/spi/spi-topcliff-pch.c+3 −4 modifieddiff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 1a85b92e9eaa3..4580b294e9373 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) spi_unregister_controller(data->host); - if (use_dma) - pch_free_dma_buf(board_dat, data); - /* check for any pending messages; no action is taken if the queue * is still full; but at least we tried. Unload anyway */ count = 500; @@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev) free_irq(board_dat->pdev->irq, data); } + if (use_dma) + pch_free_dma_buf(board_dat, data); + pci_iounmap(board_dat->pdev, data->io_remap_addr); spi_controller_put(data->host); -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"The driver releases DMA buffers before flushing its queue during unbind, leading to a use-after-free condition."
Attack vector
An attacker can trigger this vulnerability by causing the driver to unbind. This typically occurs during device removal or system shutdown procedures. The vulnerability arises from the order of operations during the unbind process, where DMA buffers are freed before ensuring all pending data transfers are completed. This can lead to a use-after-free condition if the driver attempts to access the freed DMA buffers.
Affected code
The vulnerability exists in the `pch_spi_pd_remove` function within the `drivers/spi/spi-topcliff-pch.c` file. The original code called `pch_free_dma_buf` before attempting to flush the driver's queue, creating a race condition where DMA buffers could be freed while still in use.
What the fix does
The patch reorders the operations within the `pch_spi_pd_remove` function. Specifically, it moves the call to `pch_free_dma_buf` to occur after the loop that attempts to flush the driver's queue. This ensures that the driver has a chance to complete any pending DMA operations and flush its queue before the associated DMA buffers are released, thereby preventing the use-after-free vulnerability [patch_id=5239597].
Generated on Jun 8, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- git.kernel.org/stable/c/0e8e57f9737ea257634db1d152fc430a0788a3e1nvd
- git.kernel.org/stable/c/36e58c436d2c2a797800427dc04d74ffd8b6ce1cnvd
- git.kernel.org/stable/c/43334836b907adc21eab3079d2e6b26754468786nvd
- git.kernel.org/stable/c/4ca90deeca1c7dd72c1c380ba8143565516def2dnvd
- git.kernel.org/stable/c/8822980668c96b5aa251c1e2daec1873262b8f3fnvd
- git.kernel.org/stable/c/9d72732fe70c11424bc90ed466c7ccfa58b42a9anvd
- git.kernel.org/stable/c/d50ef3553acbacce6f2843304d41d06dca358bb6nvd
- git.kernel.org/stable/c/d79e92161b65832e0b8cad5f3d84d17e5cd7a970nvd
News mentions
1- Linux Kernel: 25 Vulnerabilities Disclosed in Single Batch on June 8, 2026Vypr Intelligence · Jun 8, 2026