The Linux kernel lies at the heart of billions of devices, making any vulnerability in its drivers a top priority for quick attention. A recent bug, tracked as CVE-2024-46693, was found in Qualcomm’s PMIC Glink driver. This could cause a NULL pointer dereference during device initialization, potentially leading to system crashes or denial of service. Let’s break down how this issue occurs, how it can be exploited, and what the patch does to fix it.
What is the PMIC Glink Driver?
This is a driver used on Qualcomm SOC (System on Chip) platforms for communication between Application (AP) and Power Management IC (PMIC) subsystems. The Glink interface is used by several child drivers—UCSI, Altmode, and Battery Manager—to talk to respective hardware units.
How Does the Vulnerability Happen?
It’s all about timing. During initialization, the driver registers a "client" structure, which stores a pointer to a callback function (pdr_notify). But, if a notification fires before that pointer is set up, the kernel dereferences a NULL pointer, crashing the system.
Here’s a simplified timeline
CPU (Main thread) CPU1 (Notifier thread)
ucsi->client = NULL;
devm_pmic_glink_register_client()
--> client->pdr_notify(client->priv, pg->client_state)
--> pmic_glink_ucsi_pdr_notify()
--> schedule_work(&ucsi->register_work)
--> [context switch]
pmic_glink_ucsi_register()
ucsi_register()
pmic_glink_ucsi_read_version()
pmic_glink_ucsi_read()
pmic_glink_send(ucsi->client)
[ucsi->client is still NULL, BAD!]
ucsi->client = client; // Too late!
- The left column does the registration, leaving ucsi->client as NULL while the notifier (on the right) runs code that expects it to be valid.
## Proof of Concept / Exploitation
While this vulnerability is a race condition and timings are tight, it can be exploited in environments where the protection domain registry (added by commit 1ebcde047c54) is populated at registration time.
A malicious user (or, more likely, a buggy or incompatible kernel component) can try to trigger PMIC notifications during driver initialization to force the dereferencing of a NULL pointer, causing a local crash (DoS). This is not a privilege escalation bug, but it can be used to reliably crash a device.
Let’s consider a simplified proof-of-concept written as a kernel snippet
// Pseudocode -- not a standalone exploit
struct pmic_ucsi *ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);
ucsi->client = NULL;
devm_pmic_glink_register_client(pmic_dev, ucsi);
// This will call client's notify function and schedule work
// in a different context before ucsi->client is ready.
schedule_work(&ucsi->register_work);
// At this point, register_work depends on ucsi->client being non-NULL
// If schedule_work triggers before ucsi->client is set, kernel panic!
To trigger the bug,
Cause pmic_glink notifications to fire as early as possible.
3. The code path can hit pmic_glink_send(ucsi->client), where ucsi->client == NULL, leading to a crash.
How Was This Fixed?
The kernel patch (upstream reference) splits the allocation process:
Previously,
Allocate & register the client structure in one go.
Now,
Second, register the client.
This ensures no race can happen where the notifier triggers before the pointer is ready.
Before
ucsi->client = NULL;
devm_pmic_glink_register_client(pmic_dev, ucsi);
ucsi->client = client; // Might be too late
After
ucsi->client = alloc_client();
devm_pmic_glink_register_client(pmic_dev, ucsi->client); // Already valid!
Impact
- Affected: Linux systems running on Qualcomm SoCs using PMIC Glink with the problematic driver stack, especially since commit 1ebcde047c54.
Recommendations
- Upgrade your kernel to a version with the fixed driver. Upstream mainline and stable releases have accepted the fix.
References
- Upstream Linux Kernel Patch Discussion
- Commit Adding PD Mapper
- CVE MITRE Entry for CVE-2024-46693 (may take a few days to update)
Conclusion
This bug is a classic example of how complex, multi-threaded initialization in kernel drivers can lead to rare but potentially dangerous race conditions. Thanks to Stephen Boyd for catching it early, and the Linux community for quickly fixing it!
If you work with Qualcomm-powered devices or maintain downstream kernels, apply this patch as soon as possible to ensure stability and resilience in your systems.
Timeline
Published on: 09/13/2024 06:15:14 UTC
Last modified on: 09/13/2024 16:52:41 UTC