diff options
author | Avi Kivity <avi@redhat.com> | 2011-01-03 07:28:52 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2011-03-17 12:08:25 -0400 |
commit | a9179499350d30446d8983d272a9157963604b0f (patch) | |
tree | 32ad44938298a460f047f16f5942f037c22e853c /arch/x86/kvm/vmx.c | |
parent | d0ba64f9b4b3e41e7b91681fe04a334bc8bfc8f5 (diff) |
KVM: VMX: Avoid leaking fake realmode state to userspace
When emulating real mode, we fake some state:
- tr.base points to a fake vm86 tss
- segment registers are made to conform to vm86 restrictions
change vmx_get_segment() not to expose this fake state to userspace;
instead, return the original state.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a2e83a9729fc..87ad551b525b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -2032,23 +2032,40 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
2032 | vmcs_writel(GUEST_CR4, hw_cr4); | 2032 | vmcs_writel(GUEST_CR4, hw_cr4); |
2033 | } | 2033 | } |
2034 | 2034 | ||
2035 | static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) | ||
2036 | { | ||
2037 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
2038 | |||
2039 | return vmcs_readl(sf->base); | ||
2040 | } | ||
2041 | |||
2042 | static void vmx_get_segment(struct kvm_vcpu *vcpu, | 2035 | static void vmx_get_segment(struct kvm_vcpu *vcpu, |
2043 | struct kvm_segment *var, int seg) | 2036 | struct kvm_segment *var, int seg) |
2044 | { | 2037 | { |
2038 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
2045 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | 2039 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; |
2040 | struct kvm_save_segment *save; | ||
2046 | u32 ar; | 2041 | u32 ar; |
2047 | 2042 | ||
2043 | if (vmx->rmode.vm86_active | ||
2044 | && (seg == VCPU_SREG_TR || seg == VCPU_SREG_ES | ||
2045 | || seg == VCPU_SREG_DS || seg == VCPU_SREG_FS | ||
2046 | || seg == VCPU_SREG_GS) | ||
2047 | && !emulate_invalid_guest_state) { | ||
2048 | switch (seg) { | ||
2049 | case VCPU_SREG_TR: save = &vmx->rmode.tr; break; | ||
2050 | case VCPU_SREG_ES: save = &vmx->rmode.es; break; | ||
2051 | case VCPU_SREG_DS: save = &vmx->rmode.ds; break; | ||
2052 | case VCPU_SREG_FS: save = &vmx->rmode.fs; break; | ||
2053 | case VCPU_SREG_GS: save = &vmx->rmode.gs; break; | ||
2054 | default: BUG(); | ||
2055 | } | ||
2056 | var->selector = save->selector; | ||
2057 | var->base = save->base; | ||
2058 | var->limit = save->limit; | ||
2059 | ar = save->ar; | ||
2060 | if (seg == VCPU_SREG_TR | ||
2061 | || var->selector == vmcs_read16(sf->selector)) | ||
2062 | goto use_saved_rmode_seg; | ||
2063 | } | ||
2048 | var->base = vmcs_readl(sf->base); | 2064 | var->base = vmcs_readl(sf->base); |
2049 | var->limit = vmcs_read32(sf->limit); | 2065 | var->limit = vmcs_read32(sf->limit); |
2050 | var->selector = vmcs_read16(sf->selector); | 2066 | var->selector = vmcs_read16(sf->selector); |
2051 | ar = vmcs_read32(sf->ar_bytes); | 2067 | ar = vmcs_read32(sf->ar_bytes); |
2068 | use_saved_rmode_seg: | ||
2052 | if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state) | 2069 | if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state) |
2053 | ar = 0; | 2070 | ar = 0; |
2054 | var->type = ar & 15; | 2071 | var->type = ar & 15; |
@@ -2062,6 +2079,18 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu, | |||
2062 | var->unusable = (ar >> 16) & 1; | 2079 | var->unusable = (ar >> 16) & 1; |
2063 | } | 2080 | } |
2064 | 2081 | ||
2082 | static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) | ||
2083 | { | ||
2084 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
2085 | struct kvm_segment s; | ||
2086 | |||
2087 | if (to_vmx(vcpu)->rmode.vm86_active) { | ||
2088 | vmx_get_segment(vcpu, &s, seg); | ||
2089 | return s.base; | ||
2090 | } | ||
2091 | return vmcs_readl(sf->base); | ||
2092 | } | ||
2093 | |||
2065 | static int vmx_get_cpl(struct kvm_vcpu *vcpu) | 2094 | static int vmx_get_cpl(struct kvm_vcpu *vcpu) |
2066 | { | 2095 | { |
2067 | if (!is_protmode(vcpu)) | 2096 | if (!is_protmode(vcpu)) |