CVE-2021-47094: KVM: x86/mmu: Don't advance iterator after restart due to yielding
In the Linux kernel, the following vulnerability has been resolved:
KVM: x86/mmu: Don't advance iterator after restart due to yielding
After dropping mmu_lock in the TDP MMU, restart the iterator during
tdp_iter_next() and do not advance the iterator. Advancing the iterator
results in skipping the top-level SPTE and all its children, which is
fatal if any of the skipped SPTEs were not visited before yielding.
When zapping all SPTEs, i.e. when min_level == root_level, restarting the
iter and then invoking tdp_iter_next() is always fatal if the current gfn
has as a valid SPTE, as advancing the iterator results in try_step_side()
skipping the current gfn, which wasn't visited before yielding.
Sprinkle WARNs on iter->yielded being true in various helpers that are
often used in conjunction with yielding, and tag the helper with
__must_check to reduce the probabily of improper usage.
Failing to zap a top-level SPTE manifests in one of two ways. If a valid
SPTE is skipped by both kvm_tdp_mmu_zap_all() and kvm_tdp_mmu_put_root(),
the shadow page will be leaked and KVM will WARN accordingly.
WARNING: CPU: 1 PID: 3509 at arch/x86/kvm/mmu/tdp_mmu.c:46 [kvm]
RIP: 0010:kvm_mmu_uninit_tdp_mmu+0x3e/0x50 [kvm]
Call Trace:
<TASK>
kvm_arch_destroy_vm+0x130/0x1b0 [kvm]
kvm_destroy_vm+0x162/0x2a0 [kvm]
kvm_vcpu_release+0x34/0x60 [kvm]
__fput+0x82/0x240
task_work_run+0x5c/0x90
do_exit+0x364/0xa10
? futex_unqueue+0x38/0x60
do_group_exit+0x33/0xa0
get_signal+0x155/0x850
arch_do_signal_or_restart+0xed/0x750
exit_to_user_mode_prepare+0xc5/0x120
syscall_exit_to_user_mode+0x1d/0x40
do_syscall_64+0x48/0xc0
entry_SYSCALL_64_after_hwframe+0x44/0xae
If kvm_tdp_mmu_zap_all() skips a gfn/SPTE but that SPTE is then zapped by
kvm_tdp_mmu_put_root(), KVM triggers a use-after-free in the form of
marking a struct page as dirty/accessed after it has been put back on the
free list. This directly triggers a WARN due to encountering a page with
page_count() == 0, but it can also lead to data corruption and additional
errors in the kernel.
WARNING: CPU: 7 PID: 1995658 at arch/x86/kvm/../../../virt/kvm/kvm_main.c:171
RIP: 0010:kvm_is_zone_device_pfn.part.0+0x9e/0xd0 [kvm]
Call Trace:
<TASK>
kvm_set_pfn_dirty+0x120/0x1d0 [kvm]
__handle_changed_spte+0x92e/0xca0 [kvm]
__handle_changed_spte+0x63c/0xca0 [kvm]
__handle_changed_spte+0x63c/0xca0 [kvm]
__handle_changed_spte+0x63c/0xca0 [kvm]
zap_gfn_range+0x549/0x620 [kvm]
kvm_tdp_mmu_put_root+0x1b6/0x270 [kvm]
mmu_free_root_page+0x219/0x2c0 [kvm]
kvm_mmu_free_roots+0x1b4/0x4e0 [kvm]
kvm_mmu_unload+0x1c/0xa0 [kvm]
kvm_arch_destroy_vm+0x1f2/0x5c0 [kvm]
kvm_put_kvm+0x3b1/0x8b0 [kvm]
kvm_vcpu_release+0x4e/0x70 [kvm]
__fput+0x1f7/0x8c0
task_work_run+0xf8/0x1a0
do_exit+0x97b/0x2230
do_group_exit+0xda/0x2a0
get_signal+0x3be/0x1e50
arch_do_signal_or_restart+0x244/0x17f0
exit_to_user_mode_prepare+0xcb/0x120
syscall_exit_to_user_mode+0x1d/0x40
do_syscall_64+0x4d/0x90
entry_SYSCALL_64_after_hwframe+0x44/0xae
Note, the underlying bug existed even before commit 1af4a96025b3 ("KVM:
x86/mmu: Yield in TDU MMU iter even if no SPTES changed") moved calls to
tdp_mmu_iter_cond_resched() to the beginning of loops, as KVM could still
incorrectly advance past a top-level entry when yielding on a lower-level
entry. But with respect to leaking shadow pages, the bug was introduced
by yielding before processing the current gfn.
Alternatively, tdp_mmu_iter_cond_resched() could simply fall through, or
callers could jump to their "retry" label. The downside of that approach
is that tdp_mmu_iter_cond_resched() _must_ be called before anything else
in the loop, and there's no easy way to enfornce that requirement.
Ideally, KVM would handling the cond_resched() fully within the iterator
macro (the code is actually quite clean) and avoid this entire class of
bugs, but that is extremely difficult do wh
---truncated---
Security readout for executives and security teams
Plain-English summary
This is a high-severity Linux KVM flaw in x86 memory-management cleanup. On affected kernels, a local low-privileged actor could trigger incorrect KVM page-table handling, causing kernel warnings, leaked memory structures, use-after-free behavior, possible data corruption, and availability impact. The source bundle does not show active exploitation.
Executive priority
Treat as high priority for virtualization infrastructure. The issue is local, not proven actively exploited here, but kernel memory corruption and availability impact on KVM hosts justify prompt patch validation and operational monitoring.
Technical view
KVM x86 TDP MMU incorrectly advanced an iterator after yielding and restarting. During SPTE zapping, this could skip top-level SPTEs and children, leaving shadow pages unzapped or later touching freed pages. The CVSS vector is local, low complexity, low privileges, no user interaction, with high confidentiality and availability impact.
Likely exposure
Exposure is most relevant to Linux systems using KVM on x86 with affected kernel versions or vulnerable stable commits. Non-KVM systems, non-x86 systems, or kernels containing the referenced fixes are less likely exposed. The bundle does not identify affected distributions or cloud images.
Exploitation context
KEV is false, and the provided sources do not claim public exploitation. The CVSS vector indicates local access with low privileges is required. The bundle does not support claims of remote exploitation, unauthenticated exploitation, or weaponized exploit availability.
Researcher notes
The core failure is iterator state after tdp_mmu_iter_cond_resched yielding. Skipped SPTE traversal can cause shadow page leaks or use-after-free when later zapped. Evidence is strongest for kernel bug mechanics and fix references; exploitability beyond the CVSS vector is not established in the bundle.
Mitigation direction
Apply Linux kernel vendor updates containing the referenced KVM fixes.
Prioritize KVM virtualization hosts and systems running untrusted local workloads.
If patch timing is unclear, check distribution advisories for CVE-2021-47094.
Reduce exposure to untrusted local users until patched.
Monitor kernel logs for KVM WARN traces resembling the source description.
Validation and detection
Inventory Linux hosts using KVM on x86.
Record kernel versions and compare against vendor fixed packages.
Check whether referenced stable commits are present in custom kernels.
Review kernel logs for KVM MMU warnings or page-count warnings.
Confirm regression testing for virtual machine lifecycle operations after patching.
Generated from the cited source records. This long-tail analysis has not been individually reviewed by a named human.
Potential ATT&CK relevance
Conservative CVE-to-ATT&CK context
These mappings and lookup hints may be relevant to the vulnerability behavior, CWE, affected product, or exposure path. Glexia-inferred context is not an official MITRE, ATT&CK, CWE, or CVE Program mapping.
ATT&CK lookup starting points
Use these exact CWE pages and searches to review the Glexia ATT&CK library from this CVE's weakness and description context.
cve · low confidence lookup
CVE-2021-47094 mapping review
Open the CVE-to-ATT&CK bridge for reviewed, inferred, or future official mappings tied to this CVE.
These fields come from the CVE record and ADP containers, not from Glexia's Take. They preserve time-varying source decisions such as CISA SSVC, KEV status, CVSS metrics, and provider references.
We collect every scored CVSS vector available in the official CNA and ADP containers. When more than one version is present, the table keeps the source vectors side by side instead of collapsing them into the highest score.