In early 2021, a vulnerability was found and patched in the Linux kernel’s ACPI subsystem, specifically affecting the custom_method interface. This issue was marked as CVE-2021-46966. If you're a Linux user or developer, it's important to understand what this means, how it was fixed, and whether it could impact your systems.
This article walks through the CVE-2021-46966 bug and patch in simple language, shows the vulnerable code, and explains why the change was needed. You’ll also find references and a breakdown of how attackers could try to exploit this bug.
Before we dive in, let's explain a couple of terms
- ACPI (Advanced Configuration and Power Interface): A standard to control power and device configuration from the operating system.
- custom_method: This is a debug/prototype interface in the kernel that allows users to inject and run custom ACPI tables or methods for testing.
The Linux kernel exposes a file called custom_method under /sys/kernel/debug/acpi (when enabled), where you can write a custom ACPI method and execute it. But if the code handling this file isn’t safe, it can be an attack surface, especially since root can access it.
The Vulnerability
CVE-2021-46966 is a use-after-free bug in the implementation of cm_write(), the function that processes user input for the custom_method interface.
Use-after-free means: the code frees some memory, but keeps using (reading/writing) it after it's been released. If something else reclaimed or changed that memory, this can crash the kernel or allow local privilege escalation (root exploits).
Here’s how it happened in code
// Very simplified and partial code illustration:
static ssize_t cm_write(struct file *filp, const char __user *user_buf,
size_t count, loff_t *ppos)
{
u8 *buf;
...
buf = kmalloc(table.length, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (count < table.length) {
kfree(buf);
// <- buf is still used below! BAD
return -EINVAL;
}
copy_from_user(buf, user_buf, table.length);
...
kfree(buf); // <--- Freed at the end, always.
return rc;
}
The problem
- If a short/partial write happened (e.g., count < table.length), the buffer was freed early, but the pointer was not set to NULL, and code later in the function might still use it in later calls. Worse, the code would kfree() it again at the end, leading to a double-free.
The Fix
Linux kernel developers fixed the issue by removing the unconditional kfree(buf) at the end and setting buf = NULL in the error path, matching error handling best practices.
The key fix is:
- Only free the buffer if it hasn’t already been freed, and be sure to set it to NULL after freeing to avoid dangling pointers.
Here’s the improved code snippet
static ssize_t cm_write(struct file *filp, const char __user *user_buf,
size_t count, loff_t *ppos)
{
u8 *buf = kmalloc(table.length, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (count < table.length) {
kfree(buf);
buf = NULL; // <---- set to NULL, avoid dangling pointer
return -EINVAL;
}
copy_from_user(buf, user_buf, table.length);
...
// Do not kfree buf unconditionally; only free if needed and buf is valid.
}
You can see the commit that introduced the fix here:
🔗 kernel.org git commit
The attacker would need access to the debugfs interface, which is usually root-only.
- By carefully writing to /sys/kernel/debug/acpi/custom_method with partial data to trigger the early free and then write again, they could try to reclaim the memory with attacker-controlled data.
- If the kernel accesses the freed memory or double-frees it, this can crash the system (trigger a kernel oops) or, in rare cases, be exploited for privilege escalation.
However:
- Since this interface is only available to root by default, the practical risk is lower, but not zero. Systems that grant debugfs to less-trusted users or run in containers could potentially be at risk.
Notable patch:
acpi: custom_method: fix potential use-after-free issue
References
- CVE-2021-46966 on NVD
- Linux kernel git patch
- Linux ACPI debugfs documentation
What Should You Do?
- Most users are safe, since this interface is root-only, and debugfs is usually not mounted except in debugging scenarios.
- Admins: If you run custom or older kernels (pre-5.12), apply an update or backport the patch, especially if you provide shell or container access to less-trusted users.
- Kernel developers: Watch for all use-after-free bugs, especially in root-facing interfaces, as these can quickly escalate with a new exploit.
No known exploits in the wild, but good to patch anyway!
If you’re running Linux 5.12 or newer, you’ve got the fix. If not: update, or be careful with debugfs. As always, never expose debug interfaces to untrusted users.
Got questions? Leave a comment or check the references above for more deep-dives!
Timeline
Published on: 02/27/2024 19:04:07 UTC
Last modified on: 12/06/2024 17:55:15 UTC