The Linux kernel powers everything from servers to IoT devices, prized for its performance and reliability. But even a robust system like Linux can bear critical issues in its depths. In this post, we’ll unpack CVE-2021-47005—a flaw in the Linux kernel’s PCI endpoint framework, explain how it happens, and look at how it’s resolved. We keep the jargon low and code straightforward, so everyone gets a clear idea of what went wrong and how to stay safe.
What Is CVE-2021-47005?
CVE-2021-47005 uncovers a vulnerability where improper checking for a NULL pointer in the PCI endpoint feature function can crash the kernel. Specifically, the get_features() operation on PCI endpoints may return a NULL pointer. If a platform driver doesn’t implement this operation, the kernel can try to use an invalid memory address—leading to a full system crash.
This bug is fixed in Linux by ensuring code checks if features are present before using them. If those features aren’t found, the system now returns an error instead of crashing.
Here’s what happens inside the kernel
- When you try to bind a PCI endpoint test function (pci_epf_test), the code asks for any special endpoint controller features.
Not all drivers provide this feature function. So, the request can return a NULL.
- If code doesn’t check for this and just tries to use it, the kernel dereferences a NULL pointer, triggering an ugly crash—a NULL pointer dereference.
Here’s the call trace you might see when this happens
Call trace:
pci_epf_test_bind+xf4/x388
pci_epf_bind+x3c/x80
pci_epc_epf_link+xa8/xcc
configfs_symlink+x1a4/x48c
vfs_symlink+x104/x184
do_symlinkat+x80/xd4
__arm64_sys_symlinkat+x1c/x24
el_svc_common.constprop.3+xb8/x170
el_svc_handler+x70/x88
el_svc+x8/x640
Code: d2800581 b9403ab9 f9404ebb 8b394f60 (f940040)
---[ end trace a438e3c5a24f9df ]---
Problem Code (Vulnerable)
static int pci_epf_test_bind(struct pci_epf *epf)
{
struct pci_epc *epc = epf->epc;
// This can be NULL if not implemented!
const struct pci_epc_features *epc_features = epc->ops->get_features(epc);
// ... Later in code, accesses epc_features without NULL check
if (epc_features->bar_fixed) {
// crash if epc_features is NULL!
}
}
If get_features() isn’t implemented or returns NULL, any access like epc_features->bar_fixed will crash the kernel.
Fixed Code (Patched Version)
static int pci_epf_test_bind(struct pci_epf *epf)
{
struct pci_epc *epc = epf->epc;
const struct pci_epc_features *epc_features = NULL;
if (epc->ops->get_features)
epc_features = epc->ops->get_features(epc);
if (!epc_features) {
// Instead of crashing, report the lack of support
return -ENOTSUPP;
}
// Now safe to use epc_features!
if (epc_features->bar_fixed) {
// proceed...
}
}
How Could Attackers Exploit This?
The main risk is denial-of-service. This isn’t a remote code execution or privilege escalation bug on its own, but if untrusted users (or malicious software) can trigger endpoint binding operations, they could crash the whole system.
For example, an attacker with access could intentionally bind an endpoint that lacks the get_features support, triggering the NULL dereference and taking the server offline.
How to Patch and Stay Safe
Update your kernel. The fix was included in upstream Linux commit (for reference).
- Distributions released patches: Check with your distro’s security advisories and apply all updates for the kernel package.
- If you build your own kernel or develop drivers for PCI endpoints, manually inspect your code for safe handling of NULL values.
References
- CVE-2021-47005 on NVD
- Kernel.org commit with the patch
- Linux PCI Endpoint Framework Documentation (for developers)
Takeaway
CVE-2021-47005 is a classic example of how even powerful systems can fall to a simple check being missed. If you’re running Linux systems or writing kernel modules, always validate pointers from function hooks—especially in complex bus operations like PCI. And as always, keep your kernels patched to avoid these easy-to-trigger but devastating denial-of-service risks.
Timeline
Published on: 02/28/2024 09:15:38 UTC
Last modified on: 12/09/2024 18:23:57 UTC