summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-07-15 09:16:07 -0700
committerAndy Lutomirski <luto@amacapital.net>2014-07-15 09:16:07 -0700
commit75bd3428337407d7e1ce25f67efa1c97b63c41c4 (patch)
tree0b2206134e43556c831c01711bdd09b6c53c5194
parentb93c13e020d1e22055e7a4c66554968fb41ced60 (diff)
downloadmisc-tests-75bd3428337407d7e1ce25f67efa1c97b63c41c4.tar.gz
sigreturn: Exercise the double-fault (bad iret) paths
-rw-r--r--sigreturn.c46
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;
}