diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-07-14 14:28:49 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-07-14 14:28:49 -0700 |
commit | cb45491da0ec079ee440b36af13086722ba594ed (patch) | |
tree | f5a88ad3f8f30d78778ce85dd7ce2189022fea13 | |
parent | d9a083999ddfff824e2ddc4ae20e4ec24b0682bc (diff) | |
download | misc-tests-cb45491da0ec079ee440b36af13086722ba594ed.tar.gz |
sigreturn: Improve (and require kernel patch)
-rw-r--r-- | sigreturn.c | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/sigreturn.c b/sigreturn.c index 01f92f7..b863eab 100644 --- a/sigreturn.c +++ b/sigreturn.c @@ -14,9 +14,13 @@ #include <asm/ldt.h> #include <err.h> #include <setjmp.h> +#include <stddef.h> +#include <stdbool.h> +#include <sys/ptrace.h> +#include <sys/user.h> struct selectors { - short cs, gs, fs, __pad0; + short cs, gs, fs, ss; }; static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), @@ -49,7 +53,7 @@ static void setup_ldt(void) if ((unsigned long)stack16 > (1UL << 32) - sizeof(stack16)) errx(1, "stack16 is too high\n"); if ((unsigned long)int3 > (1UL << 32) - sizeof(int3)) - errx(1, "stack16 is too high\n"); + errx(1, "int3 is too high\n"); // Borrowed from a test case by hpa const struct user_desc code16_desc = { @@ -83,6 +87,8 @@ static void setup_ldt(void) static gregset_t initial_regs, requested_regs, resulting_regs; +static bool sig_twiddle_cs, sig_twiddle_ss; + static void sigusr1(int sig, siginfo_t *info, void *ctx_void) { ucontext_t *ctx = (ucontext_t*)ctx_void; @@ -90,17 +96,20 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void) memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS]; - sels->cs = (0 << 3) | 7; /* LDT selector 0, RPL = 3 */ - sels->__pad0 = 0; /* Avoid spurious failures. */ + if (sig_twiddle_cs) + sels->cs = (0 << 3) | 7; /* LDT selector 0, RPL = 3 */ + if (sig_twiddle_ss) + sels->ss = (1 << 3) | 7; /* LDT selector 1, RPL = 3 */ - asm volatile ("mov %0,%%ss\n\t" - "mov %0,%%ds\n\t" + /* Avoid spurious failures. */ + asm volatile ("mov %0,%%ds\n\t" "mov %0,%%es\n\t" : : "r" ((1 << 3) | 7) /* LDT selector 1, RPL = 3 */ ); - ctx->uc_mcontext.gregs[REG_RIP] = 0; - ctx->uc_mcontext.gregs[REG_RSP] = 0x8badf00d5aad0000; + ctx->uc_mcontext.gregs[REG_RIP] = + sig_twiddle_cs ? 0 : (unsigned long)&int3; + ctx->uc_mcontext.gregs[REG_RSP] = 0x8badf00d5aadc0de; memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); @@ -110,25 +119,24 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void) static void sigtrap(int sig, siginfo_t *info, void *ctx_void) { ucontext_t *ctx = (ucontext_t*)ctx_void; + struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS]; + + unsigned short ss; + asm ("mov %%ss,%0" : "=r" (ss)); + printf("\tSIGTRAP: ss = %hx, frame ss = %hx\n", ss, sels->ss); + memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t)); } static char altstack_data[SIGSTKSZ]; -int main() +static int do_test(bool twiddle_cs, bool twiddle_ss) { - setup_ldt(); - - stack_t stack = { - .ss_sp = altstack_data, - .ss_size = SIGSTKSZ, - }; - if (sigaltstack(&stack, NULL) != 0) - err(1, "sigaltstack"); - - sethandler(SIGUSR1, sigusr1, 0); - sethandler(SIGTRAP, sigtrap, SA_ONSTACK); + printf("\ttwiddle_cs = %d, twiddle_ss = %d\n", + (int)twiddle_cs, (int)twiddle_ss); + sig_twiddle_cs = twiddle_cs; + sig_twiddle_ss = twiddle_ss; raise(SIGUSR1); @@ -139,22 +147,45 @@ int main() if (i == REG_TRAPNO || i == REG_RIP) continue; /* don't care */ if (i == REG_RSP) { - printf("RSP: %llx -> %llx\n", req, res); + printf("\tRSP: %llx -> %llx\n", req, res); if (res == (req & 0xFFFFFFFF)) continue; /* OK; not expected to work */ } if (requested_regs[i] != resulting_regs[i]) { - printf("Reg %d mismatch: requested 0x%llx; got 0x%llx\n", + printf("\tReg %d mismatch: requested 0x%llx; got 0x%llx\n", i, requested_regs[i], resulting_regs[i]); nerrs++; } } - if (nerrs) { + if (nerrs) printf("[FAIL]\t%d registers were corrupted\n", nerrs); - return 1; - } else { - printf("[OK]\tall tests passed\n"); - return 0; - } + else + printf("[OK]\tall registers okay\n"); + + return nerrs; +} + +int main() +{ + int nerrs = 0; + + setup_ldt(); + + stack_t stack = { + .ss_sp = altstack_data, + .ss_size = SIGSTKSZ, + }; + if (sigaltstack(&stack, NULL) != 0) + err(1, "sigaltstack"); + + 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); + + return nerrs ? 1 : 0; } |