From 6d71f9349d9bf09bf82309bdc46704b4b6f6b314 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 12 Mar 2026 17:33:00 -0700 Subject: [PATCH] KVM: SEV: Disallow pinning more pages than exist in the system Explicitly disallow pinning more pages for an SEV VM than exist in the system to defend against absurd userspace requests without relying on somewhat arbitrary kernel functionality to prevent truly stupid KVM behavior. E.g. even with the INT_MAX check, userspace can request that KVM pin nearly 8TiB of memory, regardless of how much RAM exists in the system. Opportunistically rename "locked" to a more descriptive "total_npages". Reviewed-by: Liam Merwick Tested-by: Liam Merwick Link: https://patch.msgid.link/20260313003302.3136111-4-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/sev.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index aa4499a235f2..f37e23496b64 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -680,7 +680,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, struct kvm_sev_info *sev = to_kvm_sev_info(kvm); unsigned long npages, size; int npinned; - unsigned long locked, lock_limit; + unsigned long total_npages, lock_limit; struct page **pages; unsigned long first, last; int ret; @@ -701,10 +701,14 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, if (npages > INT_MAX) return ERR_PTR(-EINVAL); - locked = sev->pages_locked + npages; + total_npages = sev->pages_locked + npages; + if (total_npages > totalram_pages()) + return ERR_PTR(-EINVAL); + lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; - if (locked > lock_limit && !capable(CAP_IPC_LOCK)) { - pr_err("SEV: %lu locked pages exceed the lock limit of %lu.\n", locked, lock_limit); + if (total_npages > lock_limit && !capable(CAP_IPC_LOCK)) { + pr_err("SEV: %lu total pages would exceed the lock limit of %lu.\n", + total_npages, lock_limit); return ERR_PTR(-ENOMEM); } @@ -727,7 +731,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, } *n = npages; - sev->pages_locked = locked; + sev->pages_locked = total_npages; return pages;