summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFan Wu <fanwu01@zju.edu.cn>2026-07-23 11:28:41 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-07 17:18:18 +0200
commitefe7f25dd27e35063477b4b0e7eed3675669fd99 (patch)
tree00add6532dae6a62bde3774b1e6bb8726f101c82
parent0d90ab5f80e19cddfeb0c9fab47a1f34aa932075 (diff)
downloadlinux-efe7f25dd27e35063477b4b0e7eed3675669fd99.tar.gz
linux-efe7f25dd27e35063477b4b0e7eed3675669fd99.zip
mmc: via-sdmmc: stop card-detect handling on probe failure
commit 088eaa92fcebaa6b957ccf9635afdf39643a577d upstream. request_irq() registers the SD card-detect interrupt and the probe enables it before mmc_add_host() runs. If mmc_add_host() fails, the error path only unmaps the registers and returns: the interrupt stays registered, so the handler keeps running against the host once it is freed. via_sdc_isr() dereferences sdhost and its MMIO base and schedules carddet_work, which via_sdc_card_detect() also runs against freed memory through its container_of() dereference. Add a probe-error path that disables and frees the interrupt and cancels carddet_work before unmapping. carddet_work can re-enable the device interrupt via via_reset_pcictrl(), which restores PCIINTCTRL, so mask it again after cancelling the work. This issue was found by an in-house static analysis tool and confirmed by manual code review. Fixes: e4e46fb61e3b ("mmc: via-sdmmc: fix return value check of mmc_add_host()") Cc: stable@vger.kernel.org Assisted-by: Codex:gpt-5.6 Signed-off-by: Fan Wu <fanwu01@zju.edu.cn> Signed-off-by: Ulf Hansson <ulfh@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/mmc/host/via-sdmmc.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index f77457105ec3..db1feeff0faf 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -1154,10 +1154,16 @@ static int via_sd_probe(struct pci_dev *pcidev,
ret = mmc_add_host(mmc);
if (ret)
- goto unmap;
+ goto free_irq;
return 0;
+free_irq:
+ writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL);
+ free_irq(pcidev->irq, sdhost);
+ cancel_work_sync(&sdhost->carddet_work);
+ /* carddet_work may re-enable the interrupt via via_reset_pcictrl(). */
+ writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL);
unmap:
iounmap(sdhost->mmiobase);
free_mmc_host: