CVE-2024-50002 in Linux
Summary
by MITRE • 10/21/2024
In the Linux kernel, the following vulnerability has been resolved:
static_call: Handle module init failure correctly in static_call_del_module()
Module insertion invokes static_call_add_module() to initialize the static calls in a module. static_call_add_module() invokes __static_call_init(), which allocates a struct static_call_mod to either encapsulate the built-in static call sites of the associated key into it so further modules can be added or to append the module to the module chain.
If that allocation fails the function returns with an error code and the module core invokes static_call_del_module() to clean up eventually added static_call_mod entries.
This works correctly, when all keys used by the module were converted over to a module chain before the failure. If not then static_call_del_module() causes a #GP as it blindly assumes that key::mods points to a valid struct static_call_mod.
The problem is that key::mods is not a individual struct member of struct static_call_key, it's part of a union to save space:
union {
/* bit 0: 0 = mods, 1 = sites */ unsigned long type; struct static_call_mod *mods; struct static_call_site *sites; };
key::sites is a pointer to the list of built-in usage sites of the static call. The type of the pointer is differentiated by bit 0. A mods pointer has the bit clear, the sites pointer has the bit set.
As static_call_del_module() blidly assumes that the pointer is a valid static_call_mod type, it fails to check for this failure case and dereferences the pointer to the list of built-in call sites, which is obviously bogus.
Cure it by checking whether the key has a sites or a mods pointer.
If it's a sites pointer then the key is not to be touched. As the sites are walked in the same order as in __static_call_init() the site walk can be terminated because all subsequent sites have not been touched by the init code due to the error exit.
If it was converted before the allocation fail, then the inner loop which searches for a module match will find nothing.
A fail in the second allocation in __static_call_init() is harmless and does not require special treatment. The first allocation succeeded and converted the key to a module chain. That first entry has mod::mod == NULL and mod::next == NULL, so the inner loop of static_call_del_module() will neither find a module match nor a module chain. The next site in the walk was either already converted, but can't match the module, or it will exit the outer loop because it has a static_call_site pointer and not a static_call_mod pointer.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.
Analysis
by VulDB Data Team • 03/22/2026
The vulnerability described in CVE-2024-50002 resides within the Linux kernel's static call mechanism, specifically in how module initialization failures are handled during the static_call_del_module() function execution. This flaw represents a critical issue in kernel memory management and error recovery processes, potentially leading to system crashes or unauthorized access. The vulnerability manifests when a module insertion process fails during static call initialization, particularly when the system attempts to clean up partially initialized static call entries.
The technical root cause involves improper handling of a union structure within the static_call_key data structure. The key::mods field is part of a union that also contains key::sites, with the distinction between these two types determined by bit 0 of the type field. When __static_call_init() fails during allocation, static_call_del_module() attempts to clean up by blindly assuming that key::mods points to a valid struct static_call_mod. However, when the allocation failure occurs before all keys are converted to module chains, key::mods may actually point to built-in call sites rather than module entries, leading to a general protection fault (#GP) when the code attempts to dereference this invalid pointer.
This vulnerability directly relates to CWE-476 which describes NULL pointer dereference conditions, and it aligns with ATT&CK technique T1068 which involves privilege escalation through kernel vulnerabilities. The flaw occurs during the module loading process where the kernel attempts to maintain consistency between built-in static call sites and dynamically loaded modules. When an allocation failure occurs in the middle of this process, the cleanup routine fails to properly distinguish between different union types, causing a crash that could potentially be exploited to gain unauthorized system access.
The operational impact of this vulnerability is significant as it can cause system instability and potential denial of service conditions. When a module insertion fails due to memory allocation issues, the kernel's error handling mechanism itself fails, resulting in a system crash rather than graceful error recovery. This affects the reliability of kernel module loading and could be exploited by malicious actors to cause system disruptions or potentially escalate privileges. The vulnerability affects systems running Linux kernels that utilize the static call infrastructure, particularly those that frequently load and unload kernel modules.
Mitigation strategies should focus on implementing proper type checking within the static_call_del_module() function to verify whether a key points to built-in call sites or module entries before attempting cleanup operations. The fix involves checking the union type field to determine if the pointer represents a static_call_mod or static_call_site structure, ensuring that cleanup operations only proceed on valid module entries. Additionally, kernel updates should be prioritized to address this vulnerability, and system administrators should monitor for any signs of instability or unexpected crashes related to module loading. The solution also requires ensuring that error recovery paths properly handle the intermediate states where some keys may have been converted while others remain as built-in sites, preventing the system from attempting invalid memory operations during cleanup procedures.