diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-11-23 09:34:39 -0800 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-11-23 09:34:39 -0800 |
commit | 5655bd41ffedc002af69e3a8d1b0a168c22f2549 (patch) | |
tree | 5dfc9487318620d50ae8d4b8a95c6618a69ed229 | |
parent | cdf74c9634b42742f4b2c0f8bdb76ffb41d0201f (diff) | |
download | misc-tests-5655bd41ffedc002af69e3a8d1b0a168c22f2549.tar.gz |
Handle SIGSEGV and decode traps
-rw-r--r-- | sigreturn.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/sigreturn.c b/sigreturn.c index 3bdd6fd..bbf13ce 100644 --- a/sigreturn.c +++ b/sigreturn.c @@ -124,7 +124,7 @@ static void setup_ldt(void) static gregset_t initial_regs, requested_regs, resulting_regs; static volatile unsigned short sig_cs, sig_ss; -static volatile bool sig_trapped; +static volatile sig_atomic_t sig_trapped, sig_err, sig_trapno; #ifdef __x86_64__ # define REG_IP REG_RIP @@ -184,6 +184,9 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) { ucontext_t *ctx = (ucontext_t*)ctx_void; + sig_err = ctx->uc_mcontext.gregs[REG_ERR]; + sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO]; + unsigned short ss; asm ("mov %%ss,%0" : "=r" (ss)); @@ -197,7 +200,7 @@ 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; + sig_trapped = sig; } static char altstack_data[SIGSTKSZ]; @@ -342,10 +345,39 @@ static int test_bad_iret(int cs_bits, unsigned short ss, int force_cs) printf("[RUN]\t%d-bit CS (%hx), bogus SS (%hx)\n", cs_bits, sig_cs, sig_ss); - sig_trapped = false; + sig_trapped = 0; raise(SIGUSR1); if (sig_trapped) { - printf("[OK]\tGot SIGSEGV\n"); + char errdesc[32] = ""; + if (sig_err) { + const char *src = (sig_err & 1) ? " EXT" : ""; + const char *table; + if ((sig_err & 0x6) == 0x0) + table = "GDT"; + else if ((sig_err & 0x6) == 0x4) + table = "LDT"; + else if ((sig_err & 0x6) == 0x2) + table = "IDT"; + else + table = "???"; + + sprintf(errdesc, "%s%s index %d, ", + table, src, sig_err >> 3); + } + + char trapname[32]; + if (sig_trapno == 13) + strcpy(trapname, "GP"); + else if (sig_trapno == 11) + strcpy(trapname, "NP"); + else if (sig_trapno == 12) + strcpy(trapname, "SS"); + else + sprintf(trapname, "%d", sig_trapno); + + printf("[OK]\tGot #%s(0x%lx) (i.e. %s%s)\n", + trapname, (unsigned long)sig_err, + errdesc, strsignal(sig_trapped)); return 0; } else { printf("[FAIL]\tDid not get SIGSEGV\n"); @@ -381,6 +413,7 @@ int main() clearhandler(SIGTRAP); sethandler(SIGSEGV, sigtrap, SA_ONSTACK); + sethandler(SIGBUS, sigtrap, SA_ONSTACK); test_bad_iret(64, (2 << 3) | 7, -1); test_bad_iret(32, (2 << 3) | 7, -1); |