[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [Patch v4 4/4] DO NOT APPLY: Test code for interesting stack overflows
I do not recommend trying stacktest3 without stack guards - it interacts very badly between trashing the NMI stack and the NMI watchdog. --- xen/arch/x86/traps.c | 110 +++++++++++++++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/traps.c | 15 ++++++ xen/drivers/char/console.c | 8 ++++ xen/drivers/char/serial.c | 12 +++++ xen/include/xen/console.h | 1 + xen/include/xen/serial.h | 1 + 6 files changed, 147 insertions(+) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index f2be1c0..2a7fb55 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -34,6 +34,7 @@ #include <xen/console.h> #include <xen/shutdown.h> #include <xen/guest_access.h> +#include <xen/keyhandler.h> #include <asm/regs.h> #include <xen/delay.h> #include <xen/event.h> @@ -3762,6 +3763,115 @@ void asm_domain_crash_synchronous(unsigned long addr) __domain_crash_synchronous(); } +static noinline int recursion(int depth) +{ + /* junk on stack to fool naive algorithm */ + volatile unsigned long addr1 = (unsigned long)&do_get_debugreg; + volatile unsigned long tsc; + volatile unsigned long addr2 = (unsigned long)&do_set_debugreg; + + if ( depth == 0 ) + { + printk("Did you mean recursion()?\n"); + run_in_exception_handler(show_stack); + return 0; + } + else + { + int r; + rdtscll(tsc); + printk("depth %d, addr1 0x%016"PRIx64", addr2 0x%016"PRIx64", tsc %"PRIu64"\n", + depth, addr1, addr2, tsc); + r = recursion(depth-1); + if ( r ) + printk("done\n"); /* So GCC cant perform tailcall optimisation */ + return r; + } +} + +static void stacktest1(unsigned char key) +{ + printk("In %s()\n", __func__); + recursion(5); +} + +static void stacktest2(unsigned char key, struct cpu_user_regs * regs) +{ + printk("In %s()\n", __func__); + recursion(5); +} + +volatile int in_stacktest3 = 0; +unsigned long saved_sp, saved_ip, saved_flags = 0; +static void stacktest3(unsigned char key) +{ + printk("In %s()\n", __func__); + + local_irq_save(saved_flags); + in_stacktest3 = 1; + + /* Hack up an ability to longjump() out of the #DF handler. */ +recover: + asm volatile ("mov %%rsp, %0;\n\t" + : "=m"(saved_sp) ); + saved_ip = (unsigned long)&&recover; + + if ( in_stacktest3 ) + { + printk("Recovery info: sp %p, ip %p\n", + _p(saved_sp), _p(saved_ip)); + recursion(500); + } + else + printk("Recovered from #DF\n"); + + local_irq_restore(saved_flags); +} + +typedef void (*fn_ptr)(void); +static void stacktest4(unsigned char key, struct cpu_user_regs * regs) +{ + volatile fn_ptr wild_function = NULL; + printk("In %s()\n", __func__); + wild_function(); +} + +static struct keyhandler stacktest_handler[] = { + { + .irq_callback = 0, + .u.fn = stacktest1, + .desc = "Xen stack #1 - Recurse a little and see trace." + }, + + { + .irq_callback = 1, + .u.irq_fn = stacktest2, + .desc = "Xen stack #2 - Recurse a little and see trace in irq." + }, + + { + .irq_callback = 0, + .u.fn = stacktest3, + .desc = "Xen stack #3 - Cause stack overflow." + }, + + { + .irq_callback = 1, + .u.irq_fn = stacktest4, + .desc = "Xen stack #4 - Wild function pointer call." + }, + }; + +static int __init initialize_crashtable(void) +{ + register_keyhandler('1', &stacktest_handler[0]); + register_keyhandler('2', &stacktest_handler[1]); + register_keyhandler('3', &stacktest_handler[2]); + register_keyhandler('4', &stacktest_handler[3]); + return 1; +} +__initcall(initialize_crashtable); + /* * Local variables: * mode: C diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index bcf72b6..a687954 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -223,6 +223,9 @@ void show_page_walk(unsigned long addr) l1_table_offset(addr), l1e_get_intpte(l1e), pfn); } +extern volatile int in_stacktest3; +extern unsigned long saved_sp, saved_ip; + void double_fault(void); void do_double_fault(struct cpu_user_regs *regs) { @@ -250,6 +253,18 @@ void do_double_fault(struct cpu_user_regs *regs) _show_registers(regs, crs, CTXT_hypervisor, NULL); show_stack_overflow(cpu, regs); + if ( in_stacktest3 ) + { + in_stacktest3 = 0; + + undo_console_force_unlock(); + preempt_count() = 0; + enable_nmis(); + + asm volatile ("mov %0, %%rsp; jmp *%1": + : "r" (saved_sp), "r" (saved_ip) : "memory" ); + } + panic("DOUBLE FAULT -- system shutdown\n"); } diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 508f845..967fd53 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -803,6 +803,14 @@ void console_force_unlock(void) console_start_sync(); } +void undo_console_force_unlock(void) +{ + watchdog_enable(); + undo_serial_force_unlock(sercon_handle); + console_locks_busted = 0; + console_end_sync(); +} + void console_start_sync(void) { atomic_inc(&print_everything); diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c index 9b006f2..79874f1 100644 --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -380,6 +380,18 @@ void serial_force_unlock(int handle) serial_start_sync(handle); } +void undo_serial_force_unlock(int handle) +{ + struct serial_port *port; + + if ( handle == -1 ) + return; + + port = &com[handle & SERHND_IDX]; + + serial_end_sync(handle); +} + void serial_start_sync(int handle) { struct serial_port *port; diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h index cfb07a2..41c96f8 100644 --- a/xen/include/xen/console.h +++ b/xen/include/xen/console.h @@ -21,6 +21,7 @@ int console_has(const char *device); int fill_console_start_info(struct dom0_vga_console_info *); void console_force_unlock(void); +void undo_console_force_unlock(void); void console_start_sync(void); void console_end_sync(void); diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h index f38c9b7..fbdcad4 100644 --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -123,6 +123,7 @@ char serial_getc(int handle); /* Forcibly prevent serial lockup when the system is in a bad way. */ /* (NB. This also forces an implicit serial_start_sync()). */ void serial_force_unlock(int handle); +void undo_serial_force_unlock(int handle); /* Start/end a synchronous region (temporarily disable interrupt-driven tx). */ void serial_start_sync(int handle); -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |