VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46131

CVE-2026-46131

Description

In the Linux kernel, the following vulnerability has been resolved:

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

Checking is_guest_mode(vcpu) is incorrect, because translate_nested_gpa() is only valid if an L2 guest is running *with nested EPT/NPT enabled*. Instead use the same condition as translate_nested_gpa() itself.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A Linux KVM vulnerability where incorrect hypercall checks could lead to unintended nested page table operations.

Vulnerability

In the Linux kernel, KVM's x86 nested virtualization code incorrectly checked is_guest_mode(vcpu) instead of using the same condition as translate_nested_gpa() to determine whether to perform nested page table (nEPT/nNPT) slow flush hypercalls. This flaw resides in the slow-flush hypercall path and affects systems running KVM with nested virtualization enabled. The bug was introduced and fixed in the kernel stable tree; the exact affected versions span from when the faulty check was added up to the commit referenced in [1].

Exploitation

An attacker would need to be able to trigger a slow-flush hypercall while a nested guest (L2) is running without nested EPT/NPT enabled. This requires either local access to the host or the ability to influence hypercall behavior from within a guest. The attacker must also have sufficient privileges to invoke hypercalls or to cause conditions that lead to a slow flush. The exploitation sequence involves forcing the flawed code path that uses the wrong condition, potentially leading to incorrect translate_nested_gpa() calls.

Impact

Successful exploitation could result in incorrect handling of guest physical addresses during nested page table walks, potentially leading to information disclosure (reading host or other guest memory) or denial of service (system crash or instability). The impact is limited to KVM hosts with nested virtualization enabled and requires specific conditions to be met.

Mitigation

The fix is included in commit [1] applied to the Linux kernel stable tree. Users should update to a kernel version containing this commit. No workaround is available; the vulnerability is addressed by applying the patch. The issue is not currently listed on the CISA KEV.

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
4c7f8436b19a

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPaolo BonziniApr 27, 2026Fixed in 7.0.7via kernel-cna
2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
45fc766bc756

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPaolo BonziniApr 27, 2026Fixed in 6.12.88via kernel-cna
2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 79d06a8a5b7d82..0d9c62b1dd44aa 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2038,7 +2038,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 79d06a8a5b7d82..0d9c62b1dd44aa 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2038,7 +2038,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
971f17f5d910

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPaolo BonziniApr 27, 2026Fixed in 6.6.140via kernel-cna
2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 223f4fa6a849b8..96c03f95212e27 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -1987,7 +1987,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 223f4fa6a849b8..96c03f95212e27 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -1987,7 +1987,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
d6f4e217d663

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPaolo BonziniApr 27, 2026Fixed in 6.18.30via kernel-cna
2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 38595ecb990d45..f279561154bc94 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2039,7 +2039,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 38595ecb990d45..f279561154bc94 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2039,7 +2039,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
464af6fc2b1d

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPaolo BonziniApr 27, 2026Fixed in 7.1-rc3via kernel-cna
2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
d6f4e217d663

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 38595ecb990d45..f279561154bc94 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2039,7 +2039,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 38595ecb990d45..f279561154bc94 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2039,7 +2039,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
971f17f5d910

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 223f4fa6a849b8..96c03f95212e27 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -1987,7 +1987,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 223f4fa6a849b8..96c03f95212e27 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -1987,7 +1987,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
45fc766bc756

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 79d06a8a5b7d82..0d9c62b1dd44aa 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2038,7 +2038,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 79d06a8a5b7d82..0d9c62b1dd44aa 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2038,7 +2038,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
4c7f8436b19a

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
464af6fc2b1d

KVM: x86: check for nEPT/nNPT in slow flush hypercalls

2 files changed · +2 4
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    
  • arch/x86/kvm/hyperv.c+1 2 modified
    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index 9b140bbdc1d83b..4438ecac9a89bb 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
     	 * flush).  Translate the address here so the memory can be uniformly
     	 * read with kvm_read_guest().
     	 */
    -	if (!hc->fast && is_guest_mode(vcpu)) {
    +	if (!hc->fast && mmu_is_nested(vcpu)) {
     		hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
     		if (unlikely(hc->ingpa == INVALID_GPA))
     			return HV_STATUS_INVALID_HYPERCALL_INPUT;
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Incorrect condition check in `kvm_hv_flush_tlb()` — using `is_guest_mode()` instead of `mmu_is_nested()` — causes `translate_nested_gpa()` to be called when nested EPT/NPT is not enabled."

Attack vector

An attacker in a nested L2 guest that is running without nested EPT (Intel) or nested NPT (AMD) can issue a non-fast (slow) Hyper-V TLB flush hypercall. Because the original code used `is_guest_mode(vcpu)` instead of `mmu_is_nested(vcpu)`, the hypercall would attempt to translate the guest physical address via `translate_nested_gpa()` even when nested paging is not enabled. This could lead to incorrect GPA translation, potentially causing the hypercall to read or operate on the wrong memory location, or to return `HV_STATUS_INVALID_HYPERCALL_INPUT` when it should not.

Affected code

The vulnerability is in the `kvm_hv_flush_tlb()` function in `arch/x86/kvm/hyperv.c` [patch_id=2898439]. The slow (non-fast) hypercall path used `is_guest_mode(vcpu)` to decide whether to call `translate_nested_gpa()`, but this condition is too broad.

What the fix does

The patch replaces `is_guest_mode(vcpu)` with `mmu_is_nested(vcpu)` in the condition guarding the call to `translate_nested_gpa()` [patch_id=2898439]. The `mmu_is_nested()` function checks whether nested EPT or nested NPT is actually enabled, which is the same precondition that `translate_nested_gpa()` itself requires. This ensures the GPA translation is only attempted when the nested MMU is properly configured, preventing the incorrect behavior when an L2 guest is running without nested paging.

Preconditions

  • authThe attacker must be able to execute code in an L2 (nested) guest VM.
  • configThe L2 guest must be running without nested EPT (Intel) or nested NPT (AMD) enabled.
  • inputThe attacker must be able to issue a non-fast (slow) Hyper-V TLB flush hypercall to the host KVM.

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.