diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-07-14 20:18:53 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-07-14 20:18:53 -0700 |
commit | b93c13e020d1e22055e7a4c66554968fb41ced60 (patch) | |
tree | f1de414cad6b321936e332598aaa597072f8d932 | |
parent | dbfe196a0f6efedc119deb1cdbb0139dbdf609ee (diff) | |
download | misc-tests-b93c13e020d1e22055e7a4c66554968fb41ced60.tar.gz |
sigreturn: Do all available bitness combinations
-rw-r--r-- | sigreturn.c | 107 |
1 files changed, 83 insertions, 24 deletions
diff --git a/sigreturn.c b/sigreturn.c index ac68944..24dac43 100644 --- a/sigreturn.c +++ b/sigreturn.c @@ -87,7 +87,7 @@ static void setup_ldt(void) static gregset_t initial_regs, requested_regs, resulting_regs; -static bool sig_twiddle_cs, sig_twiddle_ss; +static unsigned short sig_cs, sig_ss; #ifdef __x86_64__ # define REG_IP REG_RIP @@ -121,22 +121,19 @@ static greg_t *csptr(ucontext_t *ctx) } #endif +static int nerrs; + static void sigusr1(int sig, siginfo_t *info, void *ctx_void) { ucontext_t *ctx = (ucontext_t*)ctx_void; memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); - if (sig_twiddle_cs) - *csptr(ctx) = (0 << 3) | 7; /* LDT selector 0, RPL = 3 */ - - if (sig_twiddle_ss) - *ssptr(ctx) = (1 << 3) | 7; /* LDT selector 1, RPL = 3 */ - else /* Fix for unpatched kernels. */ - asm volatile ("mov %%ss,%0" : "=r" (*ssptr(ctx))); + *csptr(ctx) = sig_cs; + *ssptr(ctx) = sig_ss; ctx->uc_mcontext.gregs[REG_IP] = - sig_twiddle_cs ? 0 : (unsigned long)&int3; + (sig_cs == 0x7) ? 0 : (unsigned long)&int3; ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL; ctx->uc_mcontext.gregs[REG_AX] = 0; @@ -152,9 +149,13 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) unsigned short ss; asm ("mov %%ss,%0" : "=r" (ss)); - printf("\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n", - ss, *ssptr(ctx), - (unsigned long long)ctx->uc_mcontext.gregs[REG_AX]); + + greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX]; + if (asm_ss != sig_ss) { + printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n", + ss, *ssptr(ctx), (unsigned long long)asm_ss); + nerrs++; + } memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t)); @@ -162,16 +163,72 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) static char altstack_data[SIGSTKSZ]; -static int do_test(bool twiddle_cs, bool twiddle_ss) +int cs_bitness(unsigned short cs) +{ + uint32_t valid = 0, ar; + asm ("lar %[cs], %[ar]\n\t" + "jnz 1f\n\t" + "mov $1, %[valid]\n\t" + "1:" + : [ar] "=r" (ar), [valid] "+rm" (valid) + : [cs] "r" (cs)); + + if (!valid) + return -1; + + bool db = (ar & (1 << 22)); + bool l = (ar & (1 << 21)); + + if (!(ar & (1<<11))) + return -1; /* Not code. */ + + if (l && !db) + return 64; + else if (!l && db) + return 32; + else if (!l && !db) + return 16; + else + return -1; /* Unknown bitness. */ +} + +int find_cs(int bitness) { - printf("\ttwiddle_cs = %d, twiddle_ss = %d\n", - (int)twiddle_cs, (int)twiddle_ss); - sig_twiddle_cs = twiddle_cs; - sig_twiddle_ss = twiddle_ss; + unsigned short my_cs; + asm ("mov %%cs,%0" : "=r" (my_cs)); + + if (cs_bitness(my_cs) == bitness) + return my_cs; + if (cs_bitness(my_cs + (2 << 3)) == bitness) + return my_cs + (2 << 3); + if (my_cs > (2<<3) && cs_bitness(my_cs - (2 << 3)) == bitness) + return my_cs - (2 << 3); + if (cs_bitness(0x7) == bitness) + return 0x7; + + printf("[WARN]\tCould not find %d-bit CS\n", bitness); + return -1; +} + +static int do_test(int cs_bits, bool use_16bit_ss) +{ + int cs = find_cs(cs_bits); + if (cs == -1) + return 0; + + if (use_16bit_ss) + sig_ss = (1 << 3) | 7; /* LDT selector 1, RPL = 3 */ + else + asm volatile ("mov %%ss,%0" : "=r" (sig_ss)); + + sig_cs = cs; + + printf("[RUN]\t%d-bit CS (%hx), %d-bit SS (%hx)\n", + cs_bits, sig_cs, use_16bit_ss ? 16 : 32, sig_ss); raise(SIGUSR1); - int nerrs = 0; + nerrs = 0; for (int i = 0; i < NGREG; i++) { greg_t req = requested_regs[i], res = resulting_regs[i]; @@ -235,7 +292,7 @@ static int do_test(bool twiddle_cs, bool twiddle_ss) int main() { - int nerrs = 0; + int total_nerrs = 0; setup_ldt(); @@ -249,10 +306,12 @@ int main() sethandler(SIGUSR1, sigusr1, 0); sethandler(SIGTRAP, sigtrap, SA_ONSTACK); - nerrs += do_test(false, false); - nerrs += do_test(true, false); - nerrs += do_test(false, true); - nerrs += do_test(true, true); + total_nerrs += do_test(64, false); + total_nerrs += do_test(32, false); + total_nerrs += do_test(16, false); + total_nerrs += do_test(64, true); + total_nerrs += do_test(32, true); + total_nerrs += do_test(16, true); - return nerrs ? 1 : 0; + return total_nerrs ? 1 : 0; } |