John Hubbard <jhubb...@nvidia.com> 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 <mi...@redhat.com> > Cc: Borislav Petkov <b...@alien8.de> > Cc: Thomas Gleixner <t...@linutronix.de> > Cc: Paolo Bonzini <pbonz...@redhat.com> > Cc: Sean Christopherson <sean.j.christopher...@intel.com> > Cc: Vitaly Kuznetsov <vkuzn...@redhat.com> > Cc: Wanpeng Li <wanpen...@tencent.com> > Cc: Jim Mattson <jmatt...@google.com> > Cc: Joerg Roedel <j...@8bytes.org> > Cc: H. Peter Anvin <h...@zytor.com> > Cc: x...@kernel.org > Cc: k...@vger.kernel.org > Signed-off-by: John Hubbard <jhubb...@nvidia.com> > --- > 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 <vkuzn...@redhat.com> -- Vitaly