John Hubbard <jhubbard@xxxxxxxxxx> writes: > There are two problems in svn_pin_memory(): > > 1) The return value of get_user_pages_fast() is stored in an > unsigned long, although the declared return value is of type int. > This will not cause any symptoms, but it is misleading. > Fix this by changing the type of npinned to "int". > > 2) The number of pages passed into get_user_pages_fast() is stored > in an unsigned long, even though get_user_pages_fast() accepts an > int. This means that it is possible to silently overflow the number > of pages. > > Fix this by adding a WARN_ON_ONCE() and an early error return. The > npages variable is left as an unsigned long for convenience in > checking for overflow. > > Fixes: 89c505809052 ("KVM: SVM: Add support for KVM_SEV_LAUNCH_UPDATE_DATA command") > Cc: Ingo Molnar <mingo@xxxxxxxxxx> > Cc: Borislav Petkov <bp@xxxxxxxxx> > Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> > Cc: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> > Cc: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> > Cc: Wanpeng Li <wanpengli@xxxxxxxxxxx> > Cc: Jim Mattson <jmattson@xxxxxxxxxx> > Cc: Joerg Roedel <joro@xxxxxxxxxx> > Cc: H. Peter Anvin <hpa@xxxxxxxxx> > Cc: x86@xxxxxxxxxx > Cc: kvm@xxxxxxxxxxxxxxx > Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx> > --- > arch/x86/kvm/svm/sev.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index 89f7f3aebd31..9693db1af57c 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -313,7 +313,8 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, > int write) > { > struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; > - unsigned long npages, npinned, size; > + unsigned long npages, size; > + int npinned; > unsigned long locked, lock_limit; > struct page **pages; > unsigned long first, last; > @@ -333,6 +334,9 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, > return NULL; > } > > + if (WARN_ON_ONCE(npages > INT_MAX)) > + return NULL; > + I bit unrelated to this patch, but callers of sev_pin_memory() treat NULL differently: sev_launch_secret()/svm_register_enc_region() return -ENOMEM sev_dbg_crypt() returns -EFAULT Should we switch to ERR_PTR() to preserve the error? > /* Avoid using vmalloc for smaller buffers. */ > size = npages * sizeof(struct page *); > if (size > PAGE_SIZE) Reviewed-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> -- Vitaly