diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-07-15 09:16:07 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-07-15 09:16:07 -0700 |
commit | 75bd3428337407d7e1ce25f67efa1c97b63c41c4 (patch) | |
tree | 0b2206134e43556c831c01711bdd09b6c53c5194 | |
parent | b93c13e020d1e22055e7a4c66554968fb41ced60 (diff) | |
download | misc-tests-75bd3428337407d7e1ce25f67efa1c97b63c41c4.tar.gz |
sigreturn: Exercise the double-fault (bad iret) paths
-rw-r--r-- | sigreturn.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/sigreturn.c b/sigreturn.c index 24dac43..bc111ab 100644 --- a/sigreturn.c +++ b/sigreturn.c @@ -35,6 +35,16 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), err(1, "sigaction"); } +static void clearhandler(int sig) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + static unsigned char stack16[65536] __attribute__((aligned(4096))); asm (".pushsection .text\n\t" @@ -87,7 +97,8 @@ static void setup_ldt(void) static gregset_t initial_regs, requested_regs, resulting_regs; -static unsigned short sig_cs, sig_ss; +static volatile unsigned short sig_cs, sig_ss; +static volatile bool sig_trapped; #ifdef __x86_64__ # define REG_IP REG_RIP @@ -151,7 +162,7 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) asm ("mov %%ss,%0" : "=r" (ss)); greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX]; - if (asm_ss != sig_ss) { + if (asm_ss != sig_ss && sig == SIGTRAP) { printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n", ss, *ssptr(ctx), (unsigned long long)asm_ss); nerrs++; @@ -159,6 +170,8 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t)); + + sig_trapped = true; } static char altstack_data[SIGSTKSZ]; @@ -290,6 +303,29 @@ static int do_test(int cs_bits, bool use_16bit_ss) return nerrs; } +static int test_bad_iret(int cs_bits) +{ + int cs = find_cs(cs_bits); + if (cs == -1) + return 0; + + sig_cs = cs; + sig_ss = (2 << 3) | 7; + + printf("[RUN]\t%d-bit CS (%hx), bogus SS (%hx)\n", + cs_bits, sig_cs, sig_ss); + + sig_trapped = false; + raise(SIGUSR1); + if (sig_trapped) { + printf("[OK]\tGot SIGSEGV\n"); + return 0; + } else { + printf("[FAIL]\tDid not get SIGSEGV\n"); + return 1; + } +} + int main() { int total_nerrs = 0; @@ -313,5 +349,11 @@ int main() total_nerrs += do_test(32, true); total_nerrs += do_test(16, true); + clearhandler(SIGTRAP); + sethandler(SIGSEGV, sigtrap, SA_ONSTACK); + + test_bad_iret(64); + test_bad_iret(32); + return total_nerrs ? 1 : 0; } |