lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 28 Apr 2021 16:46:57 +0300
From:   Valeriy Vdovin <valeriy.vdovin@...tuozzo.com>
To:     Vitaly Kuznetsov <vkuznets@...hat.com>
Cc:     linux-kernel@...r.kernel.org, Denis Lunev <den@...nvz.org>,
        Paolo Bonzini <pbonzini@...hat.com>,
        Sean Christopherson <seanjc@...gle.com>,
        Wanpeng Li <wanpengli@...cent.com>,
        Jim Mattson <jmattson@...gle.com>,
        Joerg Roedel <joro@...tes.org>,
        Thomas Gleixner <tglx@...utronix.de>,
        Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
        x86@...nel.org, "H. Peter Anvin" <hpa@...or.com>,
        Shuah Khan <shuah@...nel.org>,
        Aaron Lewis <aaronlewis@...gle.com>,
        Alexander Graf <graf@...zon.com>,
        Like Xu <like.xu@...ux.intel.com>,
        Oliver Upton <oupton@...gle.com>,
        Andrew Jones <drjones@...hat.com>, kvm@...r.kernel.org,
        linux-kselftest@...r.kernel.org
Subject: Re: [PATCH] KVM: x86: Fix KVM_GET_CPUID2 ioctl to return cpuid
 entries count

On Wed, Apr 28, 2021 at 02:38:57PM +0200, Vitaly Kuznetsov wrote:
> Valeriy Vdovin <valeriy.vdovin@...tuozzo.com> writes:
> 
> > KVM_GET_CPUID2 kvm ioctl is not very well documented, but the way it is
> > implemented in function kvm_vcpu_ioctl_get_cpuid2 suggests that even at
> > error path it will try to return number of entries to the caller. But
> > The dispatcher kvm vcpu ioctl dispatcher code in kvm_arch_vcpu_ioctl
> > ignores any output from this function if it sees the error return code.
> >
> > It's very explicit by the code that it was designed to receive some
> > small number of entries to return E2BIG along with the corrected number.
> >
> > This lost logic in the dispatcher code has been restored by removing the
> > lines that check for function return code and skip if error is found.
> > Without it, the ioctl caller will see both the number of entries and the
> > correct error.
> >
> > In selftests relevant function vcpu_get_cpuid has also been modified to
> > utilize the number of cpuid entries returned along with errno E2BIG.
> >
> > Signed-off-by: Valeriy Vdovin <valeriy.vdovin@...tuozzo.com>
> > ---
> >  arch/x86/kvm/x86.c                            | 10 +++++-----
> >  .../selftests/kvm/lib/x86_64/processor.c      | 20 +++++++++++--------
> >  2 files changed, 17 insertions(+), 13 deletions(-)
> >
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index efc7a82ab140..df8a3e44e722 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -4773,14 +4773,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> >  		r = -EFAULT;
> >  		if (copy_from_user(&cpuid, cpuid_arg, sizeof(cpuid)))
> >  			goto out;
> > +
> >  		r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid,
> >  					      cpuid_arg->entries);
> > -		if (r)
> > -			goto out;
> > -		r = -EFAULT;
> > -		if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid)))
> 
> It may make sense to check that 'r == -E2BIG' before trying to write
> anything back. I don't think it is correct/expected to modify nent in
> other cases (e.g. when kvm_vcpu_ioctl_get_cpuid2() returns -EFAULT)
> 
That's a good point. The caller could expect and rely on the fact that nent
is unmodified in any error case except E2BIG. I will add this in the next
version.
> > +
> > +		if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid))) {
> > +			r = -EFAULT;
> >  			goto out;
> > -		r = 0;
> > +		}
> >  		break;
> 
> How is KVM userspace supposed to know if it can trust the 'nent' value
> (KVM is fixed case) or not (KVM is not fixed case)? This can probably be
> resolved with adding a new capability (but then I'm not sure the change
> is worth it to be honest).

As I see it KVM userspace should set nent to 0, and then expect any non-zero
value in return along with E2BIG. This is the same approach I've used in the
modified test code in the same patch.

> Also, if making such a change, API
> documentation in virt/kvm/api.rst needs updating.

Of course. I will add changes to the documentation and comments in case if this
change in general will have a go.

> 
> >  	}
> >  	case KVM_GET_MSRS: {
> > diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> > index a8906e60a108..a412b39ad791 100644
> > --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> > +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> > @@ -727,17 +727,21 @@ struct kvm_cpuid2 *vcpu_get_cpuid(struct kvm_vm *vm, uint32_t vcpuid)
> >  
> >  	cpuid = allocate_kvm_cpuid2();
> >  	max_ent = cpuid->nent;
> > +	cpuid->nent = 0;
> >  
> > -	for (cpuid->nent = 1; cpuid->nent <= max_ent; cpuid->nent++) {
> > -		rc = ioctl(vcpu->fd, KVM_GET_CPUID2, cpuid);
> > -		if (!rc)
> > -			break;
> > +	rc = ioctl(vcpu->fd, KVM_GET_CPUID2, cpuid);
> > +	TEST_ASSERT(rc == -1 && errno == E2BIG,
> > +		    "KVM_GET_CPUID2 should return E2BIG: %d %d",
> > +		    rc, errno);
> >  
> > -		TEST_ASSERT(rc == -1 && errno == E2BIG,
> > -			    "KVM_GET_CPUID2 should either succeed or give E2BIG: %d %d",
> > -			    rc, errno);
> > -	}
> > +	TEST_ASSERT(cpuid->nent,
> > +		    "KVM_GET_CPUID2 failed to set cpuid->nent with E2BIG");
> > +
> > +	TEST_ASSERT(cpuid->nent < max_ent,
> > +		"KVM_GET_CPUID2 has %d entries, expected maximum: %d",
> > +		cpuid->nent, max_ent);
> >  
> > +	rc = ioctl(vcpu->fd, KVM_GET_CPUID2, cpuid);
> >  	TEST_ASSERT(rc == 0, "KVM_GET_CPUID2 failed, rc: %i errno: %i",
> >  		    rc, errno);
> 
> -- 
> Vitaly
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ