From: Andrew Cooper Date: Thu, 14 Jan 2016 12:24:52 +0000 (+0000) Subject: Test software injection of `into` in 32bit builds X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=9b72c4fdcbe27a87ec197733acb537fe33e0958f;p=people%2Froyger%2Fxen-test-framework.git Test software injection of `into` in 32bit builds The `into` instruction is another software interrupt, which raises an #OF trap if the overflow flag is set. It is only recognised in 32bit code however, and yields #UD if exectued in long mode. Signed-off-by: Andrew Cooper --- diff --git a/tests/swint-emulation/lowlevel.S b/tests/swint-emulation/lowlevel.S index 564f162..a0856a6 100644 --- a/tests/swint-emulation/lowlevel.S +++ b/tests/swint-emulation/lowlevel.S @@ -1,6 +1,7 @@ #include #include #include +#include /* Macro to generate a single test function. */ /* See lowlevel.h for a description of nomenclature. */ @@ -9,8 +10,15 @@ /* Function label. e.g. stub_int3_red(). */ ENTRY(stub_\insn\()_\type) - /* Avoid function label and fault label possibly aliasing. */ - nop + .if \insn == into + /* Ensure the overflow flag is set, to trigger 'into'. */ + pushf + orl $X86_EFLAGS_OF, (%esp) + popf + .else + /* Avoid function label and fault label possibly aliasing. */ + nop + .endif /* Possibly insert a Xen Forced Emulation prefix. */ .if \type == force || \type == forcered @@ -39,6 +47,8 @@ GLOBAL(label_\insn\()_\type\()_fault) .byte 0xf1 .elseif \insn == int_0x1 int $0x1 + .elseif \insn == into + into .endif /* Label where a trap should occur. e.g. label_int3_red_trap. */ @@ -65,3 +75,6 @@ GEN_SEQUENCE int3 GEN_SEQUENCE int_0x3 GEN_SEQUENCE icebp GEN_SEQUENCE int_0x1 +#ifdef __i386__ +GEN_SEQUENCE into +#endif diff --git a/tests/swint-emulation/lowlevel.h b/tests/swint-emulation/lowlevel.h index 94ed1e4..f4eaa2b 100644 --- a/tests/swint-emulation/lowlevel.h +++ b/tests/swint-emulation/lowlevel.h @@ -18,6 +18,8 @@ * - Ice Breakpoint (`0xf1`) * - int_0x1 * - `int $1` (`0xcd 0x01`) + * - into + * - `into` (`0xce`) * * Prefixes `$Y`: * - reg @@ -68,6 +70,17 @@ extern unsigned long label_int_0x1_red_trap[], label_int_0x1_red_fault[]; extern unsigned long label_int_0x1_force_trap[], label_int_0x1_force_fault[]; extern unsigned long label_int_0x1_forcered_trap[], label_int_0x1_forcered_fault[]; +#ifdef __i386__ +void stub_into_reg(void); +void stub_into_red(void); +void stub_into_force(void); +void stub_into_forcered(void); +extern unsigned long label_into_reg_trap[], label_into_reg_fault[]; +extern unsigned long label_into_red_trap[], label_into_red_fault[]; +extern unsigned long label_into_force_trap[], label_into_force_fault[]; +extern unsigned long label_into_forcered_trap[], label_into_forcered_fault[]; +#endif + #endif /* __LOWLEVEL_H__ */ /* diff --git a/tests/swint-emulation/main.c b/tests/swint-emulation/main.c index 1156f54..145530a 100644 --- a/tests/swint-emulation/main.c +++ b/tests/swint-emulation/main.c @@ -15,6 +15,7 @@ * - `int $3` (`0xcd 0x03`) * - `icebp` (`0xf1`) * - `int $1` (`0xcd 0x01`) + * - `into` (`0xce`) (32bit only) * * with and without a redundant prefix (address size override specifically, as * it has no effect on instructs like these). Each combination is executed @@ -131,6 +132,26 @@ struct sequence int_0x1 = }, }; +#ifdef __i386__ +/** Sequence for `into`. */ +struct sequence into = +{ "into", + { + {"regular", stub_into_reg, + label_into_reg_trap, label_into_reg_fault}, + + {"redundant", stub_into_red, + label_into_red_trap, label_into_red_fault}, + + {"forced", stub_into_force, + label_into_force_trap, label_into_force_fault}, + + {"forced redundant", stub_into_forcered, + label_into_forcered_trap, label_into_forcered_fault}, + }, +}; +#endif + /** Whether to run the stub in user or supervisor mode. */ static bool user = false; @@ -237,6 +258,7 @@ static void set_idt_entries_present(bool present) { idt[X86_EXC_DB].p = present; idt[X86_EXC_BP].p = present; + idt[X86_EXC_OF].p = present; } /** Modify the descriptor privilege level on the IDT entries under test. */ @@ -244,6 +266,7 @@ static void set_idt_entries_dpl(unsigned int dpl) { idt[X86_EXC_DB].dpl = dpl; idt[X86_EXC_BP].dpl = dpl; + idt[X86_EXC_OF].dpl = dpl; } /** Tests run in user mode. */ @@ -257,6 +280,9 @@ void cpl3_tests(void) test_trap(&int_0x3, X86_EXC_BP); test_trap(&icebp, X86_EXC_DB); test_trap(&int_0x1, X86_EXC_DB); +#ifdef __i386__ + test_trap(&into, X86_EXC_OF); +#endif } printk("Test cpl3: p=0\n"); @@ -267,6 +293,9 @@ void cpl3_tests(void) test_fault(&int_0x3, X86_EXC_NP, EXC_EC_SYM(BP)); test_fault(&icebp, X86_EXC_NP, EXC_EC_SYM(DB, EXT)); test_fault(&int_0x1, X86_EXC_NP, EXC_EC_SYM(DB)); +#ifdef __i386__ + test_fault(&into, X86_EXC_NP, EXC_EC_SYM(OF)); +#endif set_idt_entries_present(true); } @@ -280,6 +309,9 @@ void cpl3_tests(void) /* icebp count as external, so no dpl check. */ test_trap (&icebp, X86_EXC_DB); test_fault(&int_0x1, X86_EXC_GP, EXC_EC_SYM(DB)); +#ifdef __i386__ + test_fault(&into, X86_EXC_GP, EXC_EC_SYM(OF)); +#endif set_idt_entries_dpl(3); } @@ -296,6 +328,9 @@ void cpl0_tests(void) test_trap(&int_0x3, X86_EXC_BP); test_trap(&icebp, X86_EXC_DB); test_trap(&int_0x1, X86_EXC_DB); +#ifdef __i386__ + test_trap(&into, X86_EXC_OF); +#endif } printk("Test cpl0: p=0\n"); @@ -306,6 +341,9 @@ void cpl0_tests(void) test_fault(&int_0x3, X86_EXC_NP, EXC_EC_SYM(BP)); test_fault(&icebp, X86_EXC_NP, EXC_EC_SYM(DB, EXT)); test_fault(&int_0x1, X86_EXC_NP, EXC_EC_SYM(DB)); +#ifdef __i386__ + test_fault(&into, X86_EXC_NP, EXC_EC_SYM(OF)); +#endif set_idt_entries_present(true); }