Re: [PATCH 1/2] KVM: x86: Fix KVM_CAP_SYNC_REGS's sync_regs() TOCTOU issues

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 8/2/23 21:18, Sean Christopherson wrote:
> On Tue, Aug 01, 2023, Michal Luczaj wrote:
>> All right, so assuming the revert is not happening and the API is not misused
>> (i.e. unless vcpu->run->kvm_valid_regs is set, no one is expecting up to date
>> values in vcpu->run->s.regs), is assignment copying
>>
>> 	struct kvm_vcpu_events events = vcpu->run->s.regs.events;
>>
>> the right approach or should it be a memcpy(), like in ioctl handlers?
> 
> Both approaches are fine, though I am gaining a preference for the copy-by-value
> method.  With gcc-12 and probably most compilers, the code generation is identical
> for both as the compiler generates a call to memcpy() to handle the the struct
> assignment.
> 
> The advantage of copy-by-value for structs, and why I think I now prefer it, is
> that it provides type safety.  E.g. this compiles without complaint
> 
> 	memcpy(&events, &vcpu->run->s.regs.sregs, sizeof(events));
> 
> whereas this
> 
> 	struct kvm_vcpu_events events = vcpu->run->s.regs.sregs;
> 
> yields
> 
>   arch/x86/kvm/x86.c: In function ‘sync_regs’:
>   arch/x86/kvm/x86.c:11793:49: error: invalid initializer
>   11793 |                 struct kvm_vcpu_events events = vcpu->run->s.regs.sregs;
>         |                                                 ^~~~
> 
> The downside is that it's less obvious when reading the code that there is a
> large-ish memcpy happening, but IMO it's worth gaining the type safety.

Sure, that makes sense. I was a bit concerned how a padding within a struct
might affect performance of such copy-by-value, but (obviously?) there's no
padding in kvm_sregs, nor kvm_vcpu_events...

Anyway, while there, could you take a look at __set_sregs_common()?

	*mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0;
	static_call(kvm_x86_set_cr0)(vcpu, sregs->cr0);
	vcpu->arch.cr0 = sregs->cr0;

That last assignment seems redundant as both vmx_set_cr0() and svm_set_cr0()
take care of it, but I may be missing something (even if selftests pass with
that line removed).

thanks,
Michal




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux