Message ID | 1530228711-23597-2-git-send-email-tyhicks@canonical.com |
---|---|
State | New |
Headers | show |
Series | kvm: nVMX: Enforce cpl=0 for VMX instructions | expand |
On 29/06/18 00:31, Tyler Hicks wrote: > From: Felix Wilhelm <fwilhelm@google.com> > > VMX instructions executed inside a L1 VM will always trigger a VM exit > even when executed with cpl 3. This means we must perform the > privilege check in software. > > Fixes: 70f3aac964ae("kvm: nVMX: Remove superfluous VMX instruction fault checks") > Cc: stable@vger.kernel.org > Signed-off-by: Felix Wilhelm <fwilhelm@google.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > > (cherry picked from commit 727ba748e110b4de50d142edca9d6a9b7e6111d8) > CVE-2018-12904 > Signed-off-by: Tyler Hicks <tyhicks@canonical.com> > --- > arch/x86/kvm/vmx.c | 15 +++++++++++++-- > 1 file changed, 13 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index ddfb9914e105..d81ee9ed4e83 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -7402,6 +7402,12 @@ static int handle_vmon(struct kvm_vcpu *vcpu) > return 1; > } > > + /* CPL=0 must be checked manually. */ > + if (vmx_get_cpl(vcpu)) { > + kvm_queue_exception(vcpu, UD_VECTOR); > + return 1; > + } > + > if (vmx->nested.vmxon) { > nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION); > return kvm_skip_emulated_instruction(vcpu); > @@ -7461,6 +7467,11 @@ static int handle_vmon(struct kvm_vcpu *vcpu) > */ > static int nested_vmx_check_permission(struct kvm_vcpu *vcpu) > { > + if (vmx_get_cpl(vcpu)) { > + kvm_queue_exception(vcpu, UD_VECTOR); > + return 0; > + } > + > if (!to_vmx(vcpu)->nested.vmxon) { > kvm_queue_exception(vcpu, UD_VECTOR); > return 0; > @@ -7794,7 +7805,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) > if (get_vmx_mem_address(vcpu, exit_qualification, > vmx_instruction_info, true, &gva)) > return 1; > - /* _system ok, as hardware has verified cpl=0 */ > + /* _system ok, nested_vmx_check_permission has verified cpl=0 */ > kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva, > &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL); > } > @@ -7937,7 +7948,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) > if (get_vmx_mem_address(vcpu, exit_qualification, > vmx_instruction_info, true, &vmcs_gva)) > return 1; > - /* ok to use *_system, as hardware has verified cpl=0 */ > + /* *_system ok, nested_vmx_check_permission has verified cpl=0 */ > if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva, > (void *)&to_vmx(vcpu)->nested.current_vmptr, > sizeof(u64), &e)) { > Clean cherry pick. Acked-by: Colin Ian King <colin.king@canonical.com>
On Thu, Jun 28, 2018 at 11:31:51PM +0000, Tyler Hicks wrote: > From: Felix Wilhelm <fwilhelm@google.com> > > VMX instructions executed inside a L1 VM will always trigger a VM exit > even when executed with cpl 3. This means we must perform the > privilege check in software. > > Fixes: 70f3aac964ae("kvm: nVMX: Remove superfluous VMX instruction fault checks") > Cc: stable@vger.kernel.org > Signed-off-by: Felix Wilhelm <fwilhelm@google.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > > (cherry picked from commit 727ba748e110b4de50d142edca9d6a9b7e6111d8) > CVE-2018-12904 > Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Patch looks good. Acked-by: Seth Forshee <seth.forshee@canonical.com> Note that unstable already has this commit from the 4.17.2 stable update.
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ddfb9914e105..d81ee9ed4e83 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7402,6 +7402,12 @@ static int handle_vmon(struct kvm_vcpu *vcpu) return 1; } + /* CPL=0 must be checked manually. */ + if (vmx_get_cpl(vcpu)) { + kvm_queue_exception(vcpu, UD_VECTOR); + return 1; + } + if (vmx->nested.vmxon) { nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION); return kvm_skip_emulated_instruction(vcpu); @@ -7461,6 +7467,11 @@ static int handle_vmon(struct kvm_vcpu *vcpu) */ static int nested_vmx_check_permission(struct kvm_vcpu *vcpu) { + if (vmx_get_cpl(vcpu)) { + kvm_queue_exception(vcpu, UD_VECTOR); + return 0; + } + if (!to_vmx(vcpu)->nested.vmxon) { kvm_queue_exception(vcpu, UD_VECTOR); return 0; @@ -7794,7 +7805,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, exit_qualification, vmx_instruction_info, true, &gva)) return 1; - /* _system ok, as hardware has verified cpl=0 */ + /* _system ok, nested_vmx_check_permission has verified cpl=0 */ kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva, &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL); } @@ -7937,7 +7948,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, exit_qualification, vmx_instruction_info, true, &vmcs_gva)) return 1; - /* ok to use *_system, as hardware has verified cpl=0 */ + /* *_system ok, nested_vmx_check_permission has verified cpl=0 */ if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva, (void *)&to_vmx(vcpu)->nested.current_vmptr, sizeof(u64), &e)) {