CVE-2026-98467: KVM: arm64: nv: Fix null ptr deref on nested wp/unmap, teardown race
In the Linux kernel, the following vulnerability has been resolved:
KVM: arm64: nv: Fix null ptr deref on nested wp/unmap, teardown race
Commit 7270cc9157f4 ("KVM: arm64: nv: Handle VNCREL2 invalidation from MMU notifiers") introduced VNCREL2 invalidation in both kvmnesteds2unmap() and kvmnesteds2wp().
However at the point of this being performed concurrent stage 2 teardown of a nested guest can cause kvm->arch.mmu.pgt to be set to NULL.
This happens in kvmflushshadowall() -> kvmarchflushshadowall() -> kvmfreestage2pgd() and is performed under the kvm->mmulock.
Commit ec14c272408a ("KVM: arm64: nv: Unmap/flush shadow stage 2 page tables") introduced the teardown of the entire nested MMU range, which then invokes stage2applyrange() with resched=true:
mmunotifierinvalidaterangestart() -> ... -> kvmmmunotifierinvalidaterangestart() -> kvmmmuunmapgfnrange() -> kvmunmapgfnrange() -> kvmnesteds2unmap() -> kvmstage2unmaprange() -> unmapstage2range() -> stage2applyrange()
This means that stage2applyrange() can drop the kvm->mmulock and thus concurrent progress can be made in lockstep with kvmarchflushshadowall().
If kvmarchflushshadowall() advances ahead of stage2applyrange() and completes its operation it guarantees a NULL pointer deref.
Since kvmfreestage2pgd() is performed under the kvm->mmulock this will either be observed NULL or not and serialised against kvmfreestage2pgd().
Resolve the issue by abstracting the invalidation to a new function, kvminvalidatevncripaall(), and check that the pgt is non-NULL before dereferencing it.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
Abstract VNCR_EL2 invalidation into kvm_invalidate_vncr_ipa_all() and check that the stage-2 page-table pointer (pgt) is non-NULL before dereferencing it, serializing the check under kvm->mmu_lock.