DF-5587 / corefixed.c
/* * corefixed.c — DF-5587 fix-semantics demo: the exc_nesting re-entrancy * guard from fix.diff applied to the same reproduction. The recursive * fault is detected at depth 2, a one-line diagnostic is emitted, the * disposition reset to SIG_DFL, and the child dies of the TRUE faulting * signal (SIGSEGV) after exactly 2 handler entries — instead of 307,833 * silent re-entries. */ #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <sys/mman.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> static volatile long *depthp; #define depth (*depthp) static volatile long tls_base; /* "%gs base": 0, like cothread */ static void fault_handler(int sig, siginfo_t *si, void *ctx) { int save = errno; if (__sync_fetch_and_add(&depth, 1) != 0) { static char msg[] = "vkernel: recursive fault in exc_segfault\n"; write(2, msg, sizeof(msg) - 1); signal(SIGSEGV, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGTRAP, SIG_DFL); signal(SIGFPE, SIG_DFL); raise(sig); /* NOT REACHED */ } { volatile char *p = (volatile char *)(uintptr_t)tls_base; *p; /* fault at "mycpu" -> re-enter */ } errno = save; } int main(void) { struct sigaction sa; pid_t pid; int st; depthp = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0); if (depthp == MAP_FAILED) { perror("mmap"); return 2; } *depthp = 0; pid = fork(); if (pid == 0) { memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = fault_handler; sa.sa_flags = SA_SIGINFO | SA_NODEFER; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, NULL); { volatile char *p = (volatile char *)(uintptr_t)0x10; *p; } _exit(0); } waitpid(pid, &st, 0); printf("child: signaled=%d termsig=%d core=%d handler_entries=%ld\n", WIFSIGNALED(st), WIFSIGNALED(st) ? WTERMSIG(st) : -1, WCOREDUMP(st), depth); if (WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV && depth == 2) { printf("FIX_SEMANTICS_OK: honest SIGSEGV death after 2 " "entries with diagnostic (vs 307833 silent)\n"); return (0); } printf("UNEXPECTED\n"); return (1); } |