DF-3978 / fix.diff
diff --git a/sys/dev/virtual/nvmm/x86/nvmm_x86_svm.c b/sys/dev/virtual/nvmm/x86/nvmm_x86_svm.c index 83afb64..4cc143b 100644 --- a/sys/dev/virtual/nvmm/x86/nvmm_x86_svm.c +++ b/sys/dev/virtual/nvmm/x86/nvmm_x86_svm.c @@ -583,6 +583,9 @@ struct svm_cpudata { struct { uint64_t fsbase; uint64_t kernelgsbase; + uint64_t sysenter_cs; + uint64_t sysenter_esp; + uint64_t sysenter_eip; uint64_t drs[NVMM_X64_NDR]; #ifdef __DragonFly__ mcontext_t hmctx; /* TODO: remove this like NetBSD */ @@ -1518,6 +1521,9 @@ svm_vcpu_guest_misc_enter(struct nvmm_cpu *vcpu) /* Save the percpu host state. */ cpudata->hstate.fsbase = rdmsr(MSR_FSBASE); cpudata->hstate.kernelgsbase = rdmsr(MSR_KERNELGSBASE); + cpudata->hstate.sysenter_cs = rdmsr(MSR_SYSENTER_CS); + cpudata->hstate.sysenter_esp = rdmsr(MSR_SYSENTER_ESP); + cpudata->hstate.sysenter_eip = rdmsr(MSR_SYSENTER_EIP); } static void @@ -1534,6 +1540,17 @@ svm_vcpu_guest_misc_leave(struct nvmm_cpu *vcpu) /* Restore the percpu host state. */ wrmsr(MSR_FSBASE, cpudata->hstate.fsbase); wrmsr(MSR_KERNELGSBASE, cpudata->hstate.kernelgsbase); + + /* + * Restore the host SYSENTER MSRs. VMLOAD loads the guest values + * into the hardware MSRs and #VMEXIT does not restore the host + * values (the host save area does not cover them), so without this + * restore the guest controls IA32_SYSENTER_EIP/ESP/CS for the whole + * host and any process can pivot to ring 0 via `sysenter`. + */ + wrmsr(MSR_SYSENTER_CS, cpudata->hstate.sysenter_cs); + wrmsr(MSR_SYSENTER_ESP, cpudata->hstate.sysenter_esp); + wrmsr(MSR_SYSENTER_EIP, cpudata->hstate.sysenter_eip); } /* -------------------------------------------------------------------------- */ |