CVE-2024-26989 concerns a recently patched vulnerability in the Linux kernel affecting arm64 architectures. Specifically, this flaw occurs in the hibernation code path and can lead to a level 3 translation fault (kernel panic) when certain memory ranges are accessed. The issue has been resolved in kernel version 6.6.2+. In this article, we break down what went wrong, why it happened, and how it could have been exploited.

What is the Problem?

Hibernation in Linux, handled through functions like swsusp_save(), attempts to write system memory to disk so it can be safely restored on resume. On certain ARM64 setups, particularly when using QEMU with UEFI, with parameters rodata=off debug_pagealloc=off and a kernel built without KFENCE (CONFIG_KFENCE=n), a crash would occur:

Unable to handle kernel paging request at virtual address ffffff800000000
...
FSC = x07: level 3 translation fault
...
Internal error: Oops: 0000000096000007 [#1] SMP
...
CPU:  PID: 3663 Comm: systemd-sleep Not tainted 6.6.2+ #76
...
pc : swsusp_save+x280/x538
lr : swsusp_save+x280/x538
sp : ffffffa034a3fa40
...
Call trace:
 swsusp_save+x280/x538
 swsusp_arch_suspend+x148/x190
 hibernation_snapshot+x240/x39c
 hibernate+xc4/x378
 state_store+xf/x10c
 kobj_attr_store+x14/x24

Translation: The kernel tried to access memory it shouldn't — causing a panic.

Root Cause

The bug comes down to how the kernel determines which memory pages are "safe" to save during hibernation. Variations in the check for present pages led to the faulty assumption that MEMBLOCK_NOMAP regions (which should never be accessed or saved) are valid and should be included in the snapshot.

Originally, the logic was changed in commit a7d9f306ba70 ("arm64: drop pfn_valid_within() and simplify pfn_valid()"), and this unintentionally widened the set of memory regions scanned during hibernation.

> Summary: The kernel attempted to save and access memory regions that should never be mapped (MEMBLOCK_NOMAP), causing translation faults on some platforms.

Here's a simplified illustration of the offending flow

int page_is_saveable(page)
{
    return kernel_page_present(page);
}

int kernel_page_present(struct page *page)
{
    // Faulty logic: Skipped the crucial check for MEMBLOCK_NOMAP
    if (!can_set_direct_map()) {
        // Flaw: Assumes all pages are present.
        return 1;
    }
    // Other checks...
    return pfn_valid(page_to_pfn(page));
}

When can_set_direct_map() is false (for example, rodata=off, debug_pagealloc=off, and CONFIG_KFENCE=n), the function assumed all pages are present and accessible, regardless of whether they are actually mapped or not.

Is This a Security Threat?

In most practical terms, this bug is a denial of service (DoS) on affected arm64 platforms: attempting system hibernation can crash the system, potentially leading to data loss or availability issues. It does not appear to be directly exploitable for privilege escalation or code execution, but it can reliably crash the host or virtual machine under the right conditions.

Exploit Scenario

A malicious or unprivileged local user or automated script could trigger system hibernation (using tools like systemctl hibernate or echo disk > /sys/power/state). On a system meeting the vulnerable criteria (arm64, required kernel options, etc.), this would cause a panic and system crash — an easy way to induce denial of service on target infrastructure.

`bash

echo disk > /sys/power/state

The Fix

The solution was to skip the faulty shortcut and ensure MEMBLOCK_NOMAP pages are not considered present. The patch revises the check in kernel_page_present() to align with other architectures and always consult the correct underlying page mapping instead of trusting can_set_direct_map() status alone.

The relevant patch can be found here

- Fix commit

A simplified fixed logic

int kernel_page_present(struct page *page)
{
    // Unconditionally check pfn_valid; don't take shortcuts
    return pfn_valid(page_to_pfn(page));
}

References

- Linux Kernel Patch Commit 4e22ed6
- Upstream Discussion
- Original pfn_valid() Issue

Conclusion

CVE-2024-26989 is a classic example of how changes in low-level kernel logic can have wide-reaching consequences, especially in specialized scenarios such as hibernating with non-standard memory layouts or debug options. While the bug mostly results in denial of service (system crash/panic), its reproducibility and ease of exploitation on virtualized arm64 instances mean that all affected deployments should upgrade promptly.

> Are you at risk?
If you rely on arm64 Linux systems with custom boot parameters and allow users (or processes) to trigger hibernation, make sure you're running a kernel version with this patch applied.


Was this helpful?
For more deep dives into recent Linux CVEs, stay tuned.


Share & discuss:
- Red Hat CVE entry (when available)
- Kernel.org patch tracker


Feel free to drop any questions about this vulnerability below!

Timeline

Published on: 05/01/2024 06:15:16 UTC
Last modified on: 12/23/2024 20:43:38 UTC