CVE-2023-52490 - How a Linux Kernel Memory Migration Bug Nearly Wrecked Critical Systems

In December 2023, security researchers uncovered a subtle but dangerous flaw in the memory management subsystem of the Linux kernel, assigned as CVE-2023-52490. Triggered under certain heavy workloads, this bug could crash Linux systems during memory operations—especially when stress-testing or using memory hotplug features.

Today we’ll break down what happened in plain language, walk through (simplified) code examples, and explain how this complicated memory mapping issue could have impacted your systems.

What Was the Problem?

Linux's kernel constantly moves things around in memory: for efficiency, to defragment, or to deal with new hardware resources (like hot-add RAM). But when two things happen at once—moving a page (a chunk of memory) and trying to "offload" (remove) that same page—the kernel’s memory bookkeeping got confused.

The Crash: Kernel NULL Pointer in dentry_name

With stress-ng running hard, these crashes appeared after a few hours:

Unable to handle kernel NULL pointer dereference at virtual address 000000000000000
pc : dentry_name+xd8/x224
lr : pointer+x22c/x370
sp : ffff800025f134c
...
Call trace:
  dentry_name+xd8/x224
  pointer+x22c/x370
...
  __dump_page+x52c/x530
  dump_page+x14/x20
  set_migratetype_isolate+x110/x224
  offline_pages+x124/x474
...

The dump_page routine reads this field, expects a file mapping, and dereferences it.

- Instead, it gets an anonymous mapping pointer with the wrong flags, and the kernel crashes with a Null pointer dereference.

Why Was It Dangerous?

While this bug doesn't directly allow “code execution” so isn't likely to be remote-code-exploitable, it *is* a denial-of-service risk. It lets any unprivileged user with the capability to run heavy memory operation workloads (such as stress-ng, especially with memory hotplug) kill the system.

Moreover, the bug lies in a place that’s hard to patch without hurting performance or affecting other code. The fix needs to be careful!

What Linux Was Doing

During migration, Linux saves the old page's anon_vma pointer for bookkeeping. It *temporarily* puts this pointer in the target page's .mapping field—but doesn't set the expected flags.

Old code (simplified)

// Move to new page
target_page->mapping = old_page->anon_vma;   // no flag marking!

Elsewhere, another process checks this field

void dump_page(struct page *page) {
    struct address_space *mapping = page_mapping(page);
    // Crash! 'mapping' now is a bogus anon_vma pointer, not an address_space.
    dentry_name(mapping->host);    // NULL pointer deref!
}

page_mapping() expects lots of invariants that aren’t true here. The field points to an anon_vma, *not* a file or mapping struct, so accessing the rest of the struct is unsafe and crashes.

How Could They Fix It?

Three possible solutions were discussed (see original Linux kernel patch discussion):

Set a flag for anonymous mappings, but this would confuse other page-table walkers.

2. Grab the page lock before reading mapping, but that would slow down everything and still miss some places.
3. Save the bookkeeping data in a separate field (the .private field), instead of .mapping, *without* confusing existing code. This avoids all the mix-ups.

Fixed code (simplified)

// Save anon_vma info for migration in another field, NOT mapping
target_page->private = (unsigned long)old_page->anon_vma | state_bits;

// No risk: page_mapping() remains safe

With this, when the kernel needs to access mapping, it never gets confused—it always points to a valid mapping, and migration-related state is moved to private.

Proof-of-Concept (PoC) for reproduction

You’ll need root or enough privileges to run memory stress and hotplug. A test could look like this:

# Start stress-ng in one console
stress-ng --migrate 4 --timeout 360 &

# Start memory offlining in another console (may need root):
echo offline > /sys/devices/system/memory/memory$INDEX/state

This will trigger page migrations and hotplug/offline operations simultaneously, maximizing the race condition window.

Mitigation & Patched Versions

The fix is merged upstream as of December 2023. Distributions rolling newer kernels (6.8+) are safe, but check your vendor’s security advisories for backports:
* Kernel.org patch reference
* Red Hat Security Advisory
* Debian Security Tracker

Mitigation: Avoid enabling memory hotplug features on unpatched systems, and restrict unprivileged users from running heavy memory tests.

Final Thoughts

CVE-2023-52490 is a classic “race condition” in the Linux kernel—a conflict between two competing operations, with dangerous results. It shows how difficult kernel memory management is, and why even basic fields in complex structs can’t always be trusted.

If you run heavy virtualization, memory hotplug, or cloud workloads—update your kernel ASAP.

Further Reading

- Linux Kernel Patch Discussion
- Explaining Page Offlining and Migration (LWN.net)
- CVE-2023-52490 NVD Summary

Timeline

Published on: 03/11/2024 18:15:16 UTC
Last modified on: 01/07/2025 15:44:33 UTC