[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC v2 3/4] HVM x86 deprivileged mode: Trap handlers for deprivileged mode
Added trap handlers to catch exceptions such as a page fault, general protection fault, etc. These handlers will crash the domain as such exceptions would indicate that either there is a bug in deprivileged mode or it has been compromised by an attacker. On calling a domain_crash() whilst in deprivileged mode, we need to restore the host's context so that we do not have guest-defined registers and values in use after this point due to lazy loading of these values in the SVM and VMX implementations. Signed-off-by: Ben Catterall <Ben.Catterall@xxxxxxxxxx> Changed since v1 ---------------- * Changed to domain_crash(), domain_crash_synchronous was used previously. * Updated to perform a HVM context switch on crashing a domain * Updated hvm_deprivileged_check_trap() to return a testable error code and return based on this. --- xen/arch/x86/hvm/deprivileged.c | 54 ++++++++++++++++++++++++++++++++++++++ xen/arch/x86/traps.c | 48 +++++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/traps.c | 1 - xen/include/xen/hvm/deprivileged.h | 23 ++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/hvm/deprivileged.c b/xen/arch/x86/hvm/deprivileged.c index 994c19e..01efbe1 100644 --- a/xen/arch/x86/hvm/deprivileged.c +++ b/xen/arch/x86/hvm/deprivileged.c @@ -615,3 +615,57 @@ void hvm_deprivileged_finish_user_mode(void) hvm_deprivileged_finish_user_mode_asm(); } + +/* Check if we are in deprivileged mode */ +int is_hvm_deprivileged_vcpu(void) +{ + struct vcpu *v = get_current(); + + if( is_hvm_vcpu(v) && (v->arch.hvm_vcpu.depriv_user_mode) ) + return 1; + + return 0; +} + +/* + * Crash the domain. This should not be called if there are any memory + * allocations which will be freed by code following its invocation in the + * current execution context (current stack). This is because it causes a + * permanent 'context switch' and the current stack will be cloberred so + * any allocations made which are not freed by other paths will leak. + * This function should only be used after deprivileged mode has been + * successfully switched into, otherwise, the normal domain_crash function + * should be used. + * + * The domain which is crashed is that of the current vcpu. + * + * To crash the domain, we need to return to our privileged stack as we may have + * memory allocations which need to be cleaned up. Then, after we have returned + * to this stack, we can then crash the domain. We set a flag which we check + * when returning. + */ +void hvm_deprivileged_crash_domain(const char *reason) +{ + struct vcpu *vcpu = get_current(); + + vcpu->arch.hvm_vcpu.depriv_destroy = 1; + + printk(XENLOG_ERR "HVM Deprivileged Mode: Crashing domain. Reason: %s\n", + reason); + + /* + * Restore the processor's state. We need to do the privileged return + * path to undo any allocations that got us to this state + */ + hvm_deprivileged_finish_user_mode(); + /* DOES NOT RETURN */ +} + +/* Handle a trap event */ +int hvm_deprivileged_check_trap(const char* func_name) +{ + if( is_hvm_deprivileged_vcpu() ) + hvm_deprivileged_crash_domain(func_name); + + return 0; +} diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 9f5a6c6..df89aa9 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -74,6 +74,7 @@ #include <asm/vpmu.h> #include <public/arch-x86/cpuid.h> #include <xsm/xsm.h> +#include <xen/hvm/deprivileged.h> /* * opt_nmi: one of 'ignore', 'dom0', or 'fatal'. @@ -500,6 +501,12 @@ static void do_guest_trap( struct trap_bounce *tb; const struct trap_info *ti; + /* If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__FUNCTION__) ) + return; + trace_pv_trap(trapnr, regs->eip, use_error_code, regs->error_code); tb = &v->arch.pv_vcpu.trap_bounce; @@ -616,6 +623,11 @@ static void do_trap(struct cpu_user_regs *regs, int use_error_code) unsigned long fixup; DEBUGGER_trap_entry(trapnr, regs); + /* If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__FUNCTION__) ) + return; if ( guest_mode(regs) ) { @@ -1070,6 +1082,13 @@ void do_invalid_op(struct cpu_user_regs *regs) DEBUGGER_trap_entry(TRAP_invalid_op, regs); + /* + * If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__func__) ) + return; + if ( likely(guest_mode(regs)) ) { if ( !emulate_invalid_rdtscp(regs) && @@ -1159,6 +1178,12 @@ void do_int3(struct cpu_user_regs *regs) { DEBUGGER_trap_entry(TRAP_int3, regs); + /* If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__func__) ) + return; + if ( !guest_mode(regs) ) { debugger_trap_fatal(TRAP_int3, regs); @@ -1495,9 +1520,14 @@ void do_page_fault(struct cpu_user_regs *regs) perfc_incr(page_faults); + /* If we get a page fault whilst in HVM deprivileged mode */ + if( hvm_deprivileged_check_trap(__func__) ) + return; + if ( unlikely(fixup_page_fault(addr, regs) != 0) ) return; + if ( unlikely(!guest_mode(regs)) ) { pf_type = spurious_page_fault(addr, regs); @@ -3225,6 +3255,12 @@ void do_general_protection(struct cpu_user_regs *regs) DEBUGGER_trap_entry(TRAP_gp_fault, regs); + /* If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__func__) ) + return; + if ( regs->error_code & 1 ) goto hardware_gp; @@ -3490,6 +3526,12 @@ void do_device_not_available(struct cpu_user_regs *regs) BUG_ON(!guest_mode(regs)); + /* If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__func__) ) + return; + vcpu_restore_fpu_lazy(curr); if ( curr->arch.pv_vcpu.ctrlreg[0] & X86_CR0_TS ) @@ -3531,6 +3573,12 @@ void do_debug(struct cpu_user_regs *regs) DEBUGGER_trap_entry(TRAP_debug, regs); + /* If we take the trap whilst in HVM deprivileged mode + * then we should crash the domain. + */ + if( hvm_deprivileged_check_trap(__func__) ) + return; + if ( !guest_mode(regs) ) { if ( regs->eflags & X86_EFLAGS_TF ) diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index c7e6077..3bbfc9c 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -26,7 +26,6 @@ #include <public/callback.h> #include <asm/hvm/svm/svm.h> - static void print_xen_info(void) { char taint_str[TAINT_STRING_MAX_LEN]; diff --git a/xen/include/xen/hvm/deprivileged.h b/xen/include/xen/hvm/deprivileged.h index 2571108..9c08adf 100644 --- a/xen/include/xen/hvm/deprivileged.h +++ b/xen/include/xen/hvm/deprivileged.h @@ -106,9 +106,32 @@ void hvm_deprivileged_setup_stacks(unsigned long stack_ptr); /* Use to restore the stacks for deprivileged mode */ void hvm_deprivileged_restore_stacks(void); +/* Check if we are in deprivileged mode */ +int is_hvm_deprivileged_vcpu(void); + /* The ring 3 code */ void hvm_deprivileged_ring3(void); +/* + * Crash the domain. This should not be called if there are any memory + * allocations which will be freed by code following its invocation in the + * current execution context (current stack). This is because it causes a + * permanent 'context switch' and the current stack will be cloberred so + * any allocations made which are not freed by other paths will leak. + * This function should only be used after deprivileged mode has been + * successfully switched into, otherwise, the normal domain_crash function + * should be used. + * + * The domain which is crashed is that of the current vcpu. + */ +void hvm_deprivileged_crash_domain(const char *reason); + +/* + * Call when inside a trap that should cause a domain crash if in user mode + * e.g. an invalid_op is trapped whilst in user mode. + */ +int hvm_deprivileged_check_trap(const char* func_name); + /* The segments where the user mode .text and .data are stored */ extern unsigned long __hvm_deprivileged_text_start[]; extern unsigned long __hvm_deprivileged_text_end[]; -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |