A recent vulnerability, CVE-2024-57917, has been discovered and patched in the Linux kernel's CPU topology subsystem. This bug could trigger kernel warnings or even instability when certain /proc or /sys files are read during concurrent CPU hotplugging events (CPU addition/removal). In this post, we'll explain this vulnerability in plain language, explore how it occurs, demonstrate an exploitation scenario, and reference the fix and relevant discussions.
What Is CVE-2024-57917?
The vulnerability exists in how the kernel prints core CPU masks (which CPUs belong to the same physical core for scheduling) to user-space. The bug specifically affects core_siblings_list_read when combined with CPU hotplugging.
Check that the length calculated in (1) matches length got in (3)—if not, WARN.
If the cpumask changes between (1) and (3) (because CPUs are being hotpluggd in or out), this check fails, triggering a kernel WARNING.
Example Warning from Fuzz Testing
WARNING: CPU: 55 PID: 1168477 at lib/kasprintf.c:30 kvasprintf+x121/x130
Call Trace:
kvasprintf+x121/x130
kasprintf+xa6/xe
bitmap_print_to_buf+x89/x100
core_siblings_list_read+x7e/xb
kernfs_file_read_iter+x15b/x270
...
This shows the exact stack trace when this race condition is hit by a fuzz test.
Root Cause—A Race During cpumask Printing
- Functions like core_siblings_list_read() get called when someone does cat /sys/devices/system/cpu/cpu*/topology/core_siblings_list.
These functions eventually call kvasprintf() to print the cpumask.
- If another thread/process hotplugs CPUs at just the right moment (between two steps), the size and content calculation goes out of sync.
The critical code, simplified, looks like this
// Before the fix:
ssize_t core_siblings_list_read(struct kernfs_open_file *of, char *buf, size_t count, loff_t *ppos)
{
return cpumap_print_list_to_buf(core_cpumask);
}
Exploitation Scenario
This isn't a privilege escalation, but it is a kernel integrity bug. Frequent triggering leads to:
`bash
while true; do cat /sys/devices/system/cpu/cpu/topology/core_siblings_list > /dev/null; done
`bash
for cpu in /sys/devices/system/cpu/cpu[1-7]; do
echo > $cpu/online; sleep .05; echo 1 > $cpu/online; sleep .05
The Patch—How Was It Fixed?
The fix is simple and effective: Snapshot the cpumask before formatting it, so it can't change mid-operation.
Code Before
return cpumap_print_list_to_buf(core_cpumask);
Code After (pseudocode)
cpumask_var_t mask;
alloc_cpumask_var(&mask, GFP_KERNEL);
cpumask_copy(mask, core_cpumask);
ret = cpumap_print_list_to_buf(mask);
free_cpumask_var(mask);
- Now, regardless of CPUs being hotplugged, the buffer gets printed with a stable snapshot, and the kvasprintf length check passes.
Actual Patch
You can view the mainline patch here:
- Commit in torvalds/linux.git
- Discussion on lore.kernel.org
References
- CVE-2024-57917 (NVD entry)
- Linux kernel patch
- Upstream discussion thread
- Linux Kernel: What is cpumask?
- Report on oss-fuzz *(fictional example for illustration)*
Takeaways
- CVE-2024-57917 is a subtle but important race—an example of how even non-privileged user actions can shake kernel correctness if concurrent with system events like hotplugging.
- Admins: Consider patching if you hotplug CPUs or run in cloud/containerized environments with CPU changes at runtime.
- Kernel devs: Cache data before formatting/outputting if that data can change "under you".
- Exploitability is non-priv but log-based. No direct code execution or privilege escalation found.
Timeline
Published on: 01/19/2025 12:15:25 UTC
Last modified on: 05/04/2025 10:06:36 UTC