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 <liam.merwick@oracle.com>
Tested-by: Liam Merwick <liam.merwick@oracle.com>
Link: https://patch.msgid.link/20260313003302.3136111-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
Sean Christopherson 2026-03-12 17:33:00 -07:00
parent 12a8ff869d
commit 6d71f9349d

View File

@ -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;