Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: SEV: Drop WARN on large size for KVM_MEMORY_ENCRYPT_REG_REGION

Drop the WARN in sev_pin_memory() on npages overflowing an int, as the
WARN is comically trivially to trigger from userspace, e.g. by doing:

struct kvm_enc_region range = {
.addr = 0,
.size = -1ul,
};

__vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);

Note, the checks in sev_mem_enc_register_region() that presumably exist to
verify the incoming address+size are completely worthless, as both "addr"
and "size" are u64s and SEV is 64-bit only, i.e. they _can't_ be greater
than ULONG_MAX. That wart will be cleaned up in the near future.

if (range->addr > ULONG_MAX || range->size > ULONG_MAX)
return -EINVAL;

Opportunistically add a comment to explain why the code calculates the
number of pages the "hard" way, e.g. instead of just shifting @ulen.

Fixes: 78824fabc72e ("KVM: SVM: fix svn_pin_memory()'s use of get_user_pages_fast()")
Cc: stable@vger.kernel.org
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
Tested-by: Liam Merwick <liam.merwick@oracle.com>
Link: https://patch.msgid.link/20260313003302.3136111-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

+7 -4
+7 -4
arch/x86/kvm/svm/sev.c
··· 690 690 if (ulen == 0 || uaddr + ulen < uaddr) 691 691 return ERR_PTR(-EINVAL); 692 692 693 - /* Calculate number of pages. */ 693 + /* 694 + * Calculate the number of pages that need to be pinned to cover the 695 + * entire range. Note! This isn't simply ulen >> PAGE_SHIFT, as KVM 696 + * doesn't require the incoming address+size to be page aligned! 697 + */ 694 698 first = (uaddr & PAGE_MASK) >> PAGE_SHIFT; 695 699 last = ((uaddr + ulen - 1) & PAGE_MASK) >> PAGE_SHIFT; 696 700 npages = (last - first + 1); 701 + if (npages > INT_MAX) 702 + return ERR_PTR(-EINVAL); 697 703 698 704 locked = sev->pages_locked + npages; 699 705 lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; ··· 707 701 pr_err("SEV: %lu locked pages exceed the lock limit of %lu.\n", locked, lock_limit); 708 702 return ERR_PTR(-ENOMEM); 709 703 } 710 - 711 - if (WARN_ON_ONCE(npages > INT_MAX)) 712 - return ERR_PTR(-EINVAL); 713 704 714 705 /* Avoid using vmalloc for smaller buffers. */ 715 706 size = npages * sizeof(struct page *);