[PATCH 6/6] mfd: wm8994: Fix potential use-after-free during removal
From: Guangshuo Li
Date: Fri Oct 30 2026 - 12:55:47 EST
The IRQ chip is deleted before the codec child is removed. The codec's
IRQ cleanup can then use the freed IRQ-chip data to look up interrupt
numbers. Remove normal children before deleting the IRQ chip, and keep
the LDO children until their regulator consumers have been released.
Use late removal on probe failure as well to clean up the LDO children.
This issue was found by our static analysis tool under development.
Fixes: bb63f7d33d35 ("mfd: wm8994-core: Disable regulators before removing them")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: OpenAI:gpt-6-astra
Signed-off-by: Guangshuo Li <liguangshuo@xxxxxxxxxxxxxxx>
---
Build-tested the changed object with x86_64 defconfig plus COMPILE_TEST
and the driver dependencies (W=1).
No runtime or fault-injection testing was performed.
drivers/mfd/wm8994-core.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 094c0b3dbd97..9dbc8dbaeff2 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -29,11 +29,13 @@
static const struct mfd_cell wm8994_regulator_devs[] = {
{
.name = "wm8994-ldo",
+ .level = MFD_DEP_LEVEL_HIGH,
.id = 0,
.pm_runtime_no_callbacks = true,
},
{
.name = "wm8994-ldo",
+ .level = MFD_DEP_LEVEL_HIGH,
.id = 1,
.pm_runtime_no_callbacks = true,
},
@@ -586,7 +588,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
err_regulator_free:
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
err:
- mfd_remove_devices(wm8994->dev);
+ mfd_remove_devices_late(wm8994->dev);
return ret;
}
@@ -595,10 +597,11 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
pm_runtime_get_sync(wm8994->dev);
pm_runtime_disable(wm8994->dev);
pm_runtime_put_noidle(wm8994->dev);
+ mfd_remove_devices(wm8994->dev);
wm8994_irq_exit(wm8994);
regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
- mfd_remove_devices(wm8994->dev);
+ mfd_remove_devices_late(wm8994->dev);
}
static const struct of_device_id wm8994_of_match[] = {