CVE-2021-47037 - Understanding and Exploiting the Linux Kernel ASoC q6afe-clocks Driver Vulnerability
On modern Linux devices, sound hardware often uses the Advanced Linux Sound Architecture (ALSA) System on Chip (ASoC) framework. In early 2021, a vulnerability was found (CVE-2021-47037) in the q6afe-clocks driver, which is responsible for managing clocks for digital audio hardware on Qualcomm Snapdragon SoCs. This bug could cause the system to crash (kernel oops) under certain conditions, potentially leading to denial of service or instability after audio firmware restarts.
In this article, we break down what this bug is about, what caused it, how it can be exploited, and how it was fixed. We'll also look at code snippets and point you to more resources.
The Basics: What Is CVE-2021-47037?
CVE-2021-47037 is a vulnerability in the Linux kernel ASoC component, specifically in the sound/soc/qcom/ driver's q6afe-clocks module. The bug can cause a kernel oops if the driver is reprobed—a situation that can happen if the underlying firmware (APR services) is restarted after a crash.
What Is "Reprobing"?
"Reprobing" means the driver is loaded again for the same hardware after it was previously unloaded—often after a firmware crash. The driver wasn't written to handle being reprobed, so it breaks in this situation.
It creates and initializes a static array of clock data, using some internal data structures.
- If the driver is removed (for example, due to a firmware crash and restart) and then probed again, the driver tries to reuse the same static data.
The data (hw.init) was cleared the first time; on the second load, it's gone or invalid.
- When the code tries to access this cleared data, the kernel throws an "oops", which means it crashes.
This could allow a regular user to crash a device if they could trigger a firmware restart, resulting in a local denial of service.
Here's a simplified snippet showing part of the problematic behavior
static struct clk_hw_onecell_data afe_clks_data = {
.hws = { ... }, // Static array
.num = NUM_CLKS,
};
static int q6afe_clocks_probe(struct platform_device *pdev)
{
// ...
for (i = ; i < NUM_CLKS; i++) {
afe_clks_data.hws[i]->init = &clk_init_data[i];
clk_hw_register(NULL, afe_clks_data.hws[i]);
}
// ...
// On remove or reprobe, clk_init_data cleared, but hws still points to it!
}
After the first probe, if the driver is unloaded and probed again, clk_init_data is no longer valid, resulting in a crash.
How It Was Fixed
The fix was to rewrite the driver so that clock data is allocated and initialized at runtime instead of using static memory, making it safe to reprobe.
Here’s the main fix idea
- Instead of a big static array, dynamically allocate clock structures and their initialization data on each probe.
Simplified fixed code
static int q6afe_clocks_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *afe_clks_data;
// Allocate dynamically per probe:
afe_clks_data = devm_kzalloc(&pdev->dev, sizeof(*afe_clks_data), GFP_KERNEL);
for (i = ; i < NUM_CLKS; i++) {
afe_clks_data->hws[i] = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
afe_clks_data->hws[i]->init = &clk_init_data[i]; // Now safe
clk_hw_register(NULL, afe_clks_data->hws[i]);
}
// ...
}
Exploiting the Vulnerability
Who is at risk?
Primarily supported Qualcomm SoC platforms running affected kernel versions—typical on Android devices and some embedded Linux gadgets.
Trigger a firmware crash or restart.
On many smartphones, this isn’t directly possible without root, but badly written or bugged userspace software could cause the audio firmware to crash and restart.
Cause the q6afe-clocks driver to be reprobed.
After the firmware restarts, the device re-initializes the hardware and calls the probe function again.
The kernel crashes as soon as the driver tries to use deallocated memory it assumes is still there.
Impact:
An attacker who can trigger a firmware crash may bring the whole system down, leading to a local denial of service.
Linux Patch:
CVE Details:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-47037
Upstream commit message:
https://lore.kernel.org/all/20210423092759.20935-1-srinivas.kandagatla@linaro.org/
Linux ASoC documentation:
https://www.kernel.org/doc/html/latest/sound/soc/
Summary and Takeaways
- CVE-2021-47037 is a denial of service vulnerability in the Linux kernel’s audio clock driver for Qualcomm chips.
It is triggered by reprobing the driver after audio firmware crashes.
- The fix is to allocate data at runtime rather than using static arrays tied to the driver's probe cycle.
The issue mostly affects Android and embedded devices with affected kernels.
Stay updated and always apply kernel security fixes—like the one that resolves CVE-2021-47037—to keep your systems secure and stable!
*If you want to dive deeper into the technical details or contribute to Linux kernel security, check out the original commit and Linux ASoC subsystem documentation linked above.*
Timeline
Published on: 02/28/2024 09:15:39 UTC
Last modified on: 01/09/2025 19:47:04 UTC