| From 0a79b009525b160081d75cef5dbf45817956acf2 Mon Sep 17 00:00:00 2001 |
| From: Avi Kivity <avi@redhat.com> |
| Date: Tue, 1 Sep 2009 12:03:25 +0300 |
| Subject: KVM: VMX: Check cpl before emulating debug register access |
| |
| From: Avi Kivity <avi@redhat.com> |
| |
| commit 0a79b009525b160081d75cef5dbf45817956acf2 upstream. |
| |
| Debug registers may only be accessed from cpl 0. Unfortunately, vmx will |
| code to emulate the instruction even though it was issued from guest |
| userspace, possibly leading to an unexpected trap later. |
| |
| Signed-off-by: Avi Kivity <avi@redhat.com> |
| Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/x86/include/asm/kvm_host.h | 1 + |
| arch/x86/kvm/vmx.c | 2 ++ |
| arch/x86/kvm/x86.c | 13 +++++++++++++ |
| 3 files changed, 16 insertions(+) |
| |
| --- a/arch/x86/include/asm/kvm_host.h |
| +++ b/arch/x86/include/asm/kvm_host.h |
| @@ -618,6 +618,7 @@ void kvm_queue_exception(struct kvm_vcpu |
| void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); |
| void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, |
| u32 error_code); |
| +bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl); |
| |
| int kvm_pic_set_irq(void *opaque, int irq, int level); |
| |
| --- a/arch/x86/kvm/vmx.c |
| +++ b/arch/x86/kvm/vmx.c |
| @@ -2841,6 +2841,8 @@ static int handle_dr(struct kvm_vcpu *vc |
| unsigned long val; |
| int dr, reg; |
| |
| + if (!kvm_require_cpl(vcpu, 0)) |
| + return 1; |
| dr = vmcs_readl(GUEST_DR7); |
| if (dr & DR7_GD) { |
| /* |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -215,6 +215,19 @@ static void __queue_exception(struct kvm |
| } |
| |
| /* |
| + * Checks if cpl <= required_cpl; if true, return true. Otherwise queue |
| + * a #GP and return false. |
| + */ |
| +bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl) |
| +{ |
| + if (kvm_x86_ops->get_cpl(vcpu) <= required_cpl) |
| + return true; |
| + kvm_queue_exception_e(vcpu, GP_VECTOR, 0); |
| + return false; |
| +} |
| +EXPORT_SYMBOL_GPL(kvm_require_cpl); |
| + |
| +/* |
| * Load the pae pdptrs. Return true is they are all valid. |
| */ |
| int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3) |