diff --git a/config.yaml b/config.yaml index 7c40ce4..6eddf9e 100644 --- a/config.yaml +++ b/config.yaml @@ -56,6 +56,10 @@ actions: name: "2012-gve-Enable-reading-max-ring-size-in-DQO-QPL-mode.patch" number: 2012 + - type: "patch" + name: "2013-CVE-2026-64561-KVM-x86-Check-for-invalid-obsolete-root.patch" + number: 2013 + - replace: - target: "kernel*.config" find: | @@ -466,6 +470,7 @@ actions: - name: "Andrew Lukoshko" email: "alukoshko@almalinux.org" line: + - "KVM: x86: check for invalid/obsolete root after making MMU pages available {CVE-2026-64561}" - "hpsa: bring back deprecated PCI ids #CFHack #CFHack2024" - "mptsas: bring back deprecated PCI ids #CFHack #CFHack2024" - "megaraid_sas: bring back deprecated PCI ids #CFHack #CFHack2024" diff --git a/files/2013-CVE-2026-64561-KVM-x86-Check-for-invalid-obsolete-root.patch b/files/2013-CVE-2026-64561-KVM-x86-Check-for-invalid-obsolete-root.patch new file mode 100644 index 0000000..0c5c7ed --- /dev/null +++ b/files/2013-CVE-2026-64561-KVM-x86-Check-for-invalid-obsolete-root.patch @@ -0,0 +1,97 @@ +From 884d1cab4bfadf53f05ca36f35f06d3cc1f916a2 Mon Sep 17 00:00:00 2001 +From: CKI Backport Bot +Date: Tue, 4 Aug 2026 10:08:07 +0000 +Subject: [PATCH] KVM: x86: Check for invalid/obsolete root *after* making MMU + pages available + +JIRA: https://redhat.atlassian.net/browse/RHEL-224013 +CVE: CVE-2026-64561 +Backported from tree(s): linux + +KVM: x86: Check for invalid/obsolete root *after* making MMU pages available + +Check for a "stale" page fault, i.e. for an invalid and/or obsolete root, +after making MMU pages available for the shadow MMU. If reclaiming shadow +pages zaps an in-use root, i.e. marks it invalid, then KVM will attempt to +map memory into an invalid root. On its own, populating an invalid root is +"fine", but because child shadow pages inherit their parent's role, any +children created during the map/fetch will be created as invalid pages, +thus violating KVM's invariant that invalid pages are never on the list of +active MMU pages. + +Note, the underlying flaw has existed since KVM first started tracking +invalid roots in 2008 (commit 2e53d63acba7, "KVM: MMU: ignore zapped root +pagetables"), but the true badness only came along in 2020 (Linux 5.9) +with the invariant that invalid shadow pages can't be on the list of +active pages. + +Note #2, inheriting role.invalid when creating child shadow pages is also +far from ideal; that flaw will be addressed separately. + +Reported-by: Hyunwoo Kim +Fixes: f95eec9bed76 ("KVM: x86/mmu: Don't put invalid SPs back on the list of active pages") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2abd5287f08319fa35764566b15c6e22cb1068db) +Signed-off-by: CKI Backport Bot +--- + arch/x86/kvm/mmu/mmu.c | 9 +++++---- + arch/x86/kvm/mmu/paging_tmpl.h | 10 ++++++---- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c +index ab4bbb692064..0c4553e57731 100644 +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -4814,16 +4814,17 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault + if (r != RET_PF_CONTINUE) + return r; + +- r = RET_PF_RETRY; + write_lock(&vcpu->kvm->mmu_lock); + +- if (is_page_fault_stale(vcpu, fault)) +- goto out_unlock; +- + r = make_mmu_pages_available(vcpu); + if (r) + goto out_unlock; + ++ if (is_page_fault_stale(vcpu, fault)) { ++ r = RET_PF_RETRY; ++ goto out_unlock; ++ } ++ + r = direct_map(vcpu, fault); + + out_unlock: +diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h +index 901cd2bd40b8..6465de820e70 100644 +--- a/arch/x86/kvm/mmu/paging_tmpl.h ++++ b/arch/x86/kvm/mmu/paging_tmpl.h +@@ -827,15 +827,17 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault + } + #endif + +- r = RET_PF_RETRY; + write_lock(&vcpu->kvm->mmu_lock); + +- if (is_page_fault_stale(vcpu, fault)) +- goto out_unlock; +- + r = make_mmu_pages_available(vcpu); + if (r) + goto out_unlock; ++ ++ if (is_page_fault_stale(vcpu, fault)) { ++ r = RET_PF_RETRY; ++ goto out_unlock; ++ } ++ + r = FNAME(fetch)(vcpu, fault, &walker); + + out_unlock: +-- +GitLab +