From 5283b310e14884341f51be35253cdd59c4cb034c Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 31 Oct 2014 11:32:27 +0100 Subject: [PATCH] x86/HVM: only kill guest when unknown VM exit occurred in guest kernel mode A recent KVM change by Nadav Amit pointed out that unconditional VM exits (like VMX'es ones for the INVEPT, INVVPID, and XSETBV instructions) may result from guest user mode activity (in the example cases, e.g. prior to a privilege level check being done). Consequently convert the unconditional domain_crash() to a conditional one (when guest is in kernel mode) with the alternative of injecting #UD (when in user mode). This is meant to be a precaution against in-guest security issues introduced when any such VM exit becomes possible (on newer hardware) without the hypervisor immediately being aware of it. There are no such unhandled VM exits currently (and hence this is not an active security issue), but old (no longer security maintained) versions exhibit issues in the cases given as examples above. Suggested-by: Tim Deegan Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper Reviewed-by: Boris Ostrovsky Acked-by: Kevin Tian --- xen/arch/x86/hvm/svm/svm.c | 6 +++++- xen/arch/x86/hvm/vmx/vmx.c | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index e3e15655c5..8aca6e6a34 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -2680,7 +2680,11 @@ void svm_vmexit_handler(struct cpu_user_regs *regs) "exitinfo1 = %#"PRIx64", exitinfo2 = %#"PRIx64"\n", exit_reason, (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2); - domain_crash(v->domain); + if ( vmcb_get_cpl(vmcb) ) + hvm_inject_hw_exception(TRAP_invalid_op, + HVM_DELIVER_NO_ERROR_CODE); + else + domain_crash(v->domain); break; } diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 79a69b1d0c..0bf92b25c2 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -3161,8 +3161,19 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) /* fall through */ default: exit_and_crash: - gdprintk(XENLOG_ERR, "Bad vmexit (reason %#lx)\n", exit_reason); - domain_crash(v->domain); + { + struct segment_register ss; + + gdprintk(XENLOG_WARNING, "Bad vmexit (reason %#lx)\n", + exit_reason); + + vmx_get_segment_register(v, x86_seg_ss, &ss); + if ( ss.attr.fields.dpl ) + hvm_inject_hw_exception(TRAP_invalid_op, + HVM_DELIVER_NO_ERROR_CODE); + else + domain_crash(v->domain); + } break; } -- 2.39.5