From: Sean Christopherson Date: Fri, 1 May 2026 20:22:34 +0000 (-0700) Subject: KVM: SEV: Check PSC request indices against the actual size of the buffer X-Git-Tag: v7.1-rc6~18^2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=121d88de56bc5c0ba0ce2f6381af67f948a7e7c1;p=thirdparty%2Flinux.git KVM: SEV: Check PSC request indices against the actual size of the buffer When processing Page State Change (PSC) requests, validate the PSC buffer against the effective size of the scratch area, which could be less than the maximum size if the guest provided a pointer that isn't exactly at the start of the GHCB shared buffer. Fixes: 9b54e248d264 ("KVM: SEV: Add support to handle Page State Change VMGEXIT") Cc: stable@vger.kernel.org Reviewed-by: Tom Lendacky Reviewed-by: Michael Roth Signed-off-by: Sean Christopherson Message-ID: <20260501202250.2115252-10-seanjc@google.com> Signed-off-by: Paolo Bonzini --- diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 8577451b82b27..6e8cbae2135a3 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -3903,7 +3903,7 @@ static int snp_begin_psc(struct vcpu_svm *svm) struct kvm_vcpu *vcpu = &svm->vcpu; struct psc_hdr *hdr = &psc->hdr; struct psc_entry entry_start; - u16 idx, idx_start, idx_end; + u16 idx, idx_start, idx_end, max_nr_entries; int npages; bool huge; u64 gfn; @@ -3913,6 +3913,19 @@ static int snp_begin_psc(struct vcpu_svm *svm) return 1; } + /* + * GHCB v2 requires the scratch area to reside within the GHCB itself, + * and PSC requests are only supported for GHCB v2+. Thus it should be + * impossible to exceed the max PSC entry count (which is derived from + * the size of the shared GHCB buffer). + */ + max_nr_entries = (sev_es->ghcb_sa_len - sizeof(struct psc_hdr)) / + sizeof(struct psc_entry); + if (WARN_ON_ONCE(max_nr_entries > VMGEXIT_PSC_MAX_COUNT)) { + snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC); + return 1; + } + next_range: /* There should be no other PSCs in-flight at this point. */ if (WARN_ON_ONCE(svm->sev_es.psc_inflight)) { @@ -3928,7 +3941,7 @@ next_range: idx_start = hdr->cur_entry; idx_end = hdr->end_entry; - if (idx_end >= VMGEXIT_PSC_MAX_COUNT) { + if (idx_end >= max_nr_entries) { snp_complete_psc(svm, VMGEXIT_PSC_ERROR_INVALID_HDR); return 1; }