diff options
| author | Fan Wu <fanwu01@zju.edu.cn> | 2026-07-23 11:28:41 +0000 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-09-07 17:18:18 +0200 |
| commit | efe7f25dd27e35063477b4b0e7eed3675669fd99 (patch) | |
| tree | 00add6532dae6a62bde3774b1e6bb8726f101c82 | |
| parent | 0d90ab5f80e19cddfeb0c9fab47a1f34aa932075 (diff) | |
| download | linux-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.c | 8 |
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: |
