aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2018-07-11 13:37:18 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2018-07-15 10:27:21 -0400
commitb062b794c7831a70bda4dfac202c1a9418e06ac0 (patch)
tree1388ca0657e36b5d8004963e186e0dde6f773d9d
parentcd28325249a1ca0d771557ce823e0308ad629f98 (diff)
x86/kvm/vmx: don't read current->thread.{fs,gs}base of legacy tasks
When we switched from doing rdmsr() to reading FS/GS base values from current->thread we completely forgot about legacy 32-bit userspaces which we still support in KVM (why?). task->thread.{fsbase,gsbase} are only synced for 64-bit processes, calling save_fsgs_for_kvm() and using its result from current is illegal for legacy processes. There's no ARCH_SET_FS/GS prctls for legacy applications. Base MSRs are, however, not always equal to zero. Intel's manual says (3.4.4 Segment Loading Instructions in IA-32e Mode): "In order to set up compatibility mode for an application, segment-load instructions (MOV to Sreg, POP Sreg) work normally in 64-bit mode. An entry is read from the system descriptor table (GDT or LDT) and is loaded in the hidden portion of the segment register. ... The hidden descriptor register fields for FS.base and GS.base are physically mapped to MSRs in order to load all address bits supported by a 64-bit implementation. " The issue was found by strace test suite where 32-bit ioctl_kvm_run test started segfaulting. Reported-by: Dmitry V. Levin <ldv@altlinux.org> Bisected-by: Masatake YAMATO <yamato@redhat.com> Fixes: 42b933b59721 ("x86/kvm/vmx: read MSR_{FS,KERNEL_GS}_BASE from current->thread") Cc: stable@vger.kernel.org Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 40aa29204baf..12ed6a8f6287 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2365,6 +2365,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
2365 struct vcpu_vmx *vmx = to_vmx(vcpu); 2365 struct vcpu_vmx *vmx = to_vmx(vcpu);
2366#ifdef CONFIG_X86_64 2366#ifdef CONFIG_X86_64
2367 int cpu = raw_smp_processor_id(); 2367 int cpu = raw_smp_processor_id();
2368 unsigned long fs_base, kernel_gs_base;
2368#endif 2369#endif
2369 int i; 2370 int i;
2370 2371
@@ -2380,12 +2381,20 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
2380 vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel; 2381 vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
2381 2382
2382#ifdef CONFIG_X86_64 2383#ifdef CONFIG_X86_64
2383 save_fsgs_for_kvm(); 2384 if (likely(is_64bit_mm(current->mm))) {
2384 vmx->host_state.fs_sel = current->thread.fsindex; 2385 save_fsgs_for_kvm();
2385 vmx->host_state.gs_sel = current->thread.gsindex; 2386 vmx->host_state.fs_sel = current->thread.fsindex;
2386#else 2387 vmx->host_state.gs_sel = current->thread.gsindex;
2387 savesegment(fs, vmx->host_state.fs_sel); 2388 fs_base = current->thread.fsbase;
2388 savesegment(gs, vmx->host_state.gs_sel); 2389 kernel_gs_base = current->thread.gsbase;
2390 } else {
2391#endif
2392 savesegment(fs, vmx->host_state.fs_sel);
2393 savesegment(gs, vmx->host_state.gs_sel);
2394#ifdef CONFIG_X86_64
2395 fs_base = read_msr(MSR_FS_BASE);
2396 kernel_gs_base = read_msr(MSR_KERNEL_GS_BASE);
2397 }
2389#endif 2398#endif
2390 if (!(vmx->host_state.fs_sel & 7)) { 2399 if (!(vmx->host_state.fs_sel & 7)) {
2391 vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel); 2400 vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
@@ -2405,10 +2414,10 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
2405 savesegment(ds, vmx->host_state.ds_sel); 2414 savesegment(ds, vmx->host_state.ds_sel);
2406 savesegment(es, vmx->host_state.es_sel); 2415 savesegment(es, vmx->host_state.es_sel);
2407 2416
2408 vmcs_writel(HOST_FS_BASE, current->thread.fsbase); 2417 vmcs_writel(HOST_FS_BASE, fs_base);
2409 vmcs_writel(HOST_GS_BASE, cpu_kernelmode_gs_base(cpu)); 2418 vmcs_writel(HOST_GS_BASE, cpu_kernelmode_gs_base(cpu));
2410 2419
2411 vmx->msr_host_kernel_gs_base = current->thread.gsbase; 2420 vmx->msr_host_kernel_gs_base = kernel_gs_base;
2412 if (is_long_mode(&vmx->vcpu)) 2421 if (is_long_mode(&vmx->vcpu))
2413 wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); 2422 wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
2414#else 2423#else