Memory safety: buffer underflow in KVM SEV MMIO path
Description
The commit adds a guard to ignore MMIO requests with length 0 in the KVM SEV MMIO exit path. Prior to the patch, a length of 0 could lead to unsafe length-based calculations (e.g., computing end pointers or scratch area setup) that might underflow and cause memory corruption or other memory-safety issues. The patch returns early when len == 0, and continues using len for subsequent scratch setup and MMIO handling only when len is non-zero. This is a defensive fix for a potential buffer underflow in the SEV MMIO path and reduces the risk of memory corruption stemming from zero-length MMIO handling.
Proof of Concept
This demonstrates the underlying risk pattern in a safe, user-space simulation (not a kernel exploit):
#include <stdio.h>
#include <stdint.h>
// Vulnerable-like simulation: zero-length path leads to end pointer underflow
int vulnerable_sim() {
unsigned char buf[64];
unsigned long long len = 0; // simulate 0-length MMIO
unsigned char *start = buf;
unsigned char *end = start + len - 1; // underflow when len == 0
// Unsafe access that would occur in the vulnerable path
*end = 'A';
return 0;
}
// Patched behavior: 0-length MMIO is ignored
int patched_sim() {
unsigned char buf[64];
unsigned long long len = 0; // simulate 0-length MMIO
if (len == 0) {
// ignore 0-length MMIO requests
return 0;
}
unsigned char *start = buf;
unsigned char *end = start + len - 1;
*end = 'A';
return 0;
}
int main(){ vulnerable_sim(); patched_sim(); return 0; }
Commit Details
Author: Sean Christopherson
Date: 2026-05-01 20:22 UTC
Message:
KVM: SEV: Ignore MMIO requests of length '0'
Explicitly ignore MMIO requests of length '0', so that setting up the
software scratch area (and other code) doesn't have to worry about
underflowing the length, and to allow for special casing '0' in the
future.
Fixes: 8f423a80d299 ("KVM: SVM: Support MMIO for an SEV-ES guest")
Cc: stable@vger.kernel.org
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20260501202250.2115252-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Triage Assessment
Vulnerability Type: Memory safety (buffer underflow)
Confidence: MEDIUM
Reasoning:
The patch adds a guard to ignore MMIO requests with length 0, preventing potential underflow and memory-safety issues when setting up the scratch area and handling MMIO. This reduces the risk of memory corruption or related exploits stemming from zero-length MMIO handling.
Verification Assessment
Vulnerability Type: Memory safety: buffer underflow in KVM SEV MMIO path
Confidence: MEDIUM
Affected Versions: v7.0-rc6 (KVM SEV MMIO path; patch targets 0-length MMIO handling in sev_handle_vmgexit).
Code Diff
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 23170b64f4a33d..fb2174b6d1ba43 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -4497,13 +4497,17 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
case SVM_VMGEXIT_MMIO_READ:
case SVM_VMGEXIT_MMIO_WRITE: {
bool is_write = control->exit_code == SVM_VMGEXIT_MMIO_WRITE;
+ u64 len = control->exit_info_2;
- ret = setup_vmgexit_scratch(svm, !is_write, control->exit_info_2);
+ if (!len)
+ return 1;
+
+ ret = setup_vmgexit_scratch(svm, !is_write, len);
if (ret)
break;
- ret = kvm_sev_es_mmio(vcpu, is_write, control->exit_info_1,
- control->exit_info_2, svm->sev_es.ghcb_sa);
+ ret = kvm_sev_es_mmio(vcpu, is_write, control->exit_info_1, len,
+ svm->sev_es.ghcb_sa);
break;
}
case SVM_VMGEXIT_NMI_COMPLETE: