Re: [PATCH v2] KVM: nVMX: Fix memory corruption when using VMCS shadowing

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

 




On 09/07/2016 00:36, Jim Mattson wrote:
> When freeing the nested resources of a vcpu, there is an assumption that
> the vcpu's vmcs01 is the current VMCS on the CPU that executes
> nested_release_vmcs12(). If this assumption is violated, the vcpu's
> vmcs01 may be made active on multiple CPUs at the same time, in
> violation of Intel's specification. Moreover, since the vcpu's vmcs01 is
> not VMCLEARed on every CPU on which it is active, it can linger in a
> CPU's VMCS cache after it has been freed and potentially
> repurposed. Subsequent eviction from the CPU's VMCS cache on a capacity
> miss can result in memory corruption.
> 
> It is not sufficient for vmx_free_vcpu() to call vmx_load_vmcs01(). If
> the vcpu in question was last loaded on a different CPU, it must be
> migrated to the current CPU before calling vmx_load_vmcs01().
> 
> Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx>
> 
> ---
>  arch/x86/kvm/vmx.c  | 19 +++++++++++++++++--
>  virt/kvm/kvm_main.c |  2 ++
>  2 files changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 003618e..afb1ab3 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -8855,6 +8855,22 @@ static void vmx_load_vmcs01(struct kvm_vcpu *vcpu)
>  	put_cpu();
>  }
>  
> +/*
> + * Ensure that the current vmcs of the logical processor is the
> + * vmcs01 of the vcpu before calling free_nested().
> + */
> +static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
> +{
> +       struct vcpu_vmx *vmx = to_vmx(vcpu);
> +       int r;
> +
> +       r = vcpu_load(vcpu);
> +       BUG_ON(r);
> +       vmx_load_vmcs01(vcpu);
> +       free_nested(vmx);
> +       vcpu_put(vcpu);
> +}
> +
>  static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_vmx *vmx = to_vmx(vcpu);
> @@ -8863,8 +8879,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
>  		vmx_destroy_pml_buffer(vmx);
>  	free_vpid(vmx->vpid);
>  	leave_guest_mode(vcpu);
> -	vmx_load_vmcs01(vcpu);
> -	free_nested(vmx);
> +	vmx_free_vcpu_nested(vcpu);
>  	free_loaded_vmcs(vmx->loaded_vmcs);
>  	kfree(vmx->guest_msrs);
>  	kvm_vcpu_uninit(vcpu);
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 48bd520..dd25346 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -148,6 +148,7 @@ int vcpu_load(struct kvm_vcpu *vcpu)
>  	put_cpu();
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vcpu_load);
>  
>  void vcpu_put(struct kvm_vcpu *vcpu)
>  {
> @@ -157,6 +158,7 @@ void vcpu_put(struct kvm_vcpu *vcpu)
>  	preempt_enable();
>  	mutex_unlock(&vcpu->mutex);
>  }
> +EXPORT_SYMBOL_GPL(vcpu_put);
>  
>  static void ack_flush(void *_completed)
>  {
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Looks good, thanks!  I haven't yet pushed it out, but I plan to send it
to Linus for 4.7.  So also

Cc: stable <stable@xxxxxxxxxxxxxxx>

Thanks,

Paolo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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