In early 2021, a significant bug was found and fixed in the Linux kernel's MediaTek IOMMU (Input-Output Memory Management Unit) driver (commit). This vulnerability, tracked as CVE-2021-47025, could lead to kernel warnings or potential undefined behaviors when a MediaTek-based device resumes from suspend. In this post, we’ll explain the issue, cover its exploitability, and walk through key code snippets in simple terms.
Quick Summary
- Component: Linux kernel drivers/iommu/mtk_iommu.c (MediaTek IOMMU driver)
- Problem: On device resume, the clock may remain disabled if certain conditions are met, leading to errors or warnings when another part of the system tries to disable it again.
- Root Cause: The driver's resume function, mtk_iommu_runtime_resume(), didn't always re-enable the clock (even when needed) if a certain pointer (m4u_dom) was NULL.
On affected kernels, users see scary kernel log messages like
[ 1.586104] infra_m4u already disabled
[ 1.586133] WARNING: CPU: PID: 121 at drivers/clk/clk.c:952 clk_core_disable+xb/xb8
...
[ 1.810728] ------------[ cut here ]------------
The clock for the IOMMU is being disabled when it’s already off.
- This triggers a kernel warning (and cut here trace), which, while not a direct security bug, is a sign of deeper issues and can break hardware stability, sometimes opening a door for further exploitation via failed power management.
Digging Into The Code
Before the fix, the core bug was that clock enabling on resume only happened if the IOMMU domain (m4u_dom) existed. Here’s an abstracted/snipped version of the faulty logic in mtk_iommu_runtime_resume():
int mtk_iommu_runtime_resume(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
if (data->m4u_dom)
clk_prepare_enable(data->bclk);
// ...
}
If m4u_dom was NULL, the clock never got enabled during runtime resume.
The patch made sure the clock is always enabled during resume, regardless of that pointer
int mtk_iommu_runtime_resume(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
// Always enable the clock
clk_prepare_enable(data->bclk);
// ... rest of initialization
}
Link to patch:
- kernel.org commit 6a7e2cb1d51e
## Exploit Details / How Could It Be Abused?
Flood kernel logs with warnings (cut here traces).
- Potentially lock up the IOMMU, causing device or peripheral failures (such as broken multimedia or GPU access).
A user or malicious app with the ability to trigger runtime power management (PM) events could
- Repeatedly suspend/resume the device, clogging system logs, and potentially crashing device drivers due to inconsistent clock/power state.
This could require a reboot to restore normal operation.
### 3. Kernel Panic / Potential Primitive For Later Exploits
Though the upstream commit only covers kernel warnings, improperly managed clocks can sometimes lead to *double-free* or *use-after-free* patterns elsewhere in PM code, if not carefully handled. Attackers could leverage this for privilege escalation under very specific, though unlikely, conditions.
A minimal pseudo-C userland snippet to trigger suspend/resume
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
int main() {
// Open a device node that uses the mtk-iommu, e.g., /dev/ion (if present)
int fd = open("/dev/ion", O_RDWR);
for (int i = ; i < 100; ++i) {
// This is platform dependent! Trigger runtime PM suspend/resume.
ioctl(fd, /* some IOCTL to trigger PM */, );
// Or echo 'auto' to /sys/class/devices/10205000.iommu/power/control
}
close(fd);
return ;
}
Alternate method
# From shell, simulate repeated suspends (may require root!)
for i in {1..100}; do
echo mem > /sys/power/state
# Wake the device back up after each suspend
done
Kernel Patch:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6a7e2cb1d51ec78d568d1aa59eb6a60bdc2b3c7f
CVE Record:
https://nvd.nist.gov/vuln/detail/CVE-2021-47025
LKML Discussion:
https://lore.kernel.org/all/20210421145113.8192-1-yong.wu@mediatek.com/
Summary: How to Stay Safe
- Upgrade your kernel: Any Linux kernel >= 5.13 (or earlier with backported patch) should include the fix.
- Embedded/Android Vendors: Urgently apply the patch to avoid erratic runtime PM handling.
- End users: If your Android phone or SoC-powered device gets “stuck” or unstable after activity involving suspend/resume, consult your vendor for a patch or update.
- Developers: Always double-check power/clock management callbacks for symmetry and unhandled NULL cases.
Final Thoughts
While CVE-2021-47025 may seem like a minor power bug, even “simple” kernel bugs can have a snowball effect in embedded Linux or Android systems. Always keep your systems updated and check the security advisories!
Exclusive content for security researchers and Linux maintainers. ❤️
If you have questions about other embedded kernel bugs, drop them in the comments below!
Timeline
Published on: 02/28/2024 09:15:39 UTC
Last modified on: 12/06/2024 18:52:52 UTC