blob: 4a037b04e89fc786cd76b03dfea7289b18f3366d [file] [log] [blame]
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#include "util.h"
static char* p;
static void sighandler(__attribute__((unused)) int sig) {
p[1] = 78;
signal(SIGSEGV, SIG_DFL);
}
int main(void) {
pid_t child;
int status;
int pipe_fds[2];
size_t page_size = sysconf(_SC_PAGESIZE);
p = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED,
-1, 0);
test_assert(MAP_FAILED != p);
p[0] = 0;
p[1] = 0;
test_assert(0 == pipe(pipe_fds));
if (0 == (child = fork())) {
char ch;
read(pipe_fds[0], &ch, 1);
signal(SIGSEGV, sighandler);
p[0] = 77;
/* trigger SIGSEGV */
crash_null_deref();
return 77;
}
test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));
test_assert(child == waitpid(child, &status, 0));
test_assert(status == ((SIGSTOP << 8) | 0x7f));
test_assert(1 == write(pipe_fds[1], "x", 1));
test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));
test_assert(child == waitpid(child, &status, 0));
test_assert(status == ((SIGSEGV << 8) | 0x7f));
/* Check that the child actually executed forwards to the SIGSEGV */
test_assert(p[0] == 77);
test_assert(p[1] == 0);
/* Progress to second (fatal) SIGSEGV */
test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)SIGSEGV));
test_assert(child == waitpid(child, &status, 0));
test_assert(status == ((SIGSEGV << 8) | 0x7f));
test_assert(p[0] == 77);
/* Check that code actually ran */
test_assert(p[1] == 78);
/* Continue with the signal again. This should be fatal. */
test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)SIGSEGV));
test_assert(child == waitpid(child, &status, 0));
test_assert(WIFSIGNALED(status));
test_assert(WTERMSIG(status) == SIGSEGV);
atomic_puts("EXIT-SUCCESS");
return 0;
}