---

The Linux Kernel is the centerpiece of all Linux distributions, and KVM (Kernel-based Virtual Machine) is a widely used virtualization core. A subtle but important vulnerability, CVE-2024-26990, appeared in KVM's x86 memory management. In this article, we'll walk through what happened, show you the core code involved, and explain how it can be abused. We’ll keep the language clear—no crazy jargon. Links to the Linux kernel patch and other resources are included along the way.

Dirty Logging keeps track of which pages VMs write to—crucial for things like live migration.

When running nested virtualization (a VM inside a VM, aka L2 inside L1), KVM relies on the TDP MMU (Two-Dimensional Paging Memory Management Unit). It uses special bits (“D-bits”) to track if guest pages are “dirty.”

What Was Wrong? (Attack Scenario)

KVM’s code wasn’t doing the right thing when tracking L2 guest’s writes—if certain features were enabled/disabled (specifically when using EPT, or Extended Page Tables, and PML, or Page Modification Logging), it didn’t write-protect the memory properly. Because of this, KVM could miss writes made by an L2 guest—those would never show up in the dirty log!

What’s the risk?

Attackers (with control over L2 guests or possibly even L1 guests) could make changes to memory that the KVM host wouldn't notice. This could allow bypassing introspection, snapshot, or migration tools that depend on knowing which memory was changed.

During migration, data is stale or inconsistent.

- An attacker could inject code or data into memory that security tools wouldn't scan or migrate correctly.

A proof-of-concept (PoC) would involve setting up a nested VM and writing to specific pages, then checking from the host's dirty log if these are registered. If not: you hit the bug!

Key Code Snippet: Before and After Patch

The heart of the fix is checking kvm_mmu_page_ad_need_write_protect() before deciding whether to write-protect or just clear the D-bit (dirty bit) on TDP MMU SPTEs (Shadow Page Table Entries).

Problem Code (Before)

if (clear_dirty) {
    // Just clear the dirty bit, don't write-protect
    spte = spte & ~SPTE_DIRTY_BIT;
} else {
    // Write-protect maybe?
    spte = spte | SPTE_WRITE_PROTECT;
}

*This ignores some cases where you must write-protect the page no matter what clear_dirty says!*

Fixed Code (After)

bool need_wp = kvm_mmu_page_ad_need_write_protect(page);

if (clear_dirty || need_wp) {
    // Always write-protect if needed, or if clearing the dirty bit
    spte = (spte & ~SPTE_DIRTY_BIT) | SPTE_WRITE_PROTECT;
}

*Now, even if you’re just clearing the dirty bit, you’ll protect the page if necessary for nested EPT+PML cases.*

Commit diff here

Patch Reference and Resources

- Official Patch (git.kernel.org)
- CVE Record (MITRE)
- KVM Community Discussion Thread

An L1 guest that disables EPT.

But enterprise clouds and advanced virtualization setups will hit this case. Migration and security software can have major problems.

How To Patch or Mitigate

- Upgrade your kernel: If you use virtualization with KVM and allow nested guests, update to a kernel with this fix (>= 6.9-rc1).

Disable PML or nested EPT temporarily if you cannot update.

- Keep your cloud/virtualization and security tools up to date.

Conclusion

CVE-2024-26990 shows how subtle issues deep in the kernel can have big security impacts for advanced users. It lets dirty writes in nested VMs go unnoticed, endangering migration and security tools. The fix ensures that every time a dirty bit is cleared, the page is also write-protected if needed, making sure you catch every write.

Timeline

Published on: 05/01/2024 06:15:16 UTC
Last modified on: 05/04/2025 09:01:37 UTC