1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Copyright 2017 John Sperbeck 5 * 6 * Test that an access to a mapped but inaccessible area causes a SEGV and 7 * reports si_code == SEGV_ACCERR. 8 */ 9 10 #include <stdbool.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <signal.h> 16 #include <sys/mman.h> 17 #include <assert.h> 18 #include <ucontext.h> 19 20 #include "utils.h" 21 22 static bool faulted; 23 static int si_code; 24 25 static void segv_handler(int n, siginfo_t *info, void *ctxt_v) 26 { 27 ucontext_t *ctxt = (ucontext_t *)ctxt_v; 28 struct pt_regs *regs = ctxt->uc_mcontext.regs; 29 30 faulted = true; 31 si_code = info->si_code; 32 regs->nip += 4; 33 } 34 35 int test_segv_errors(void) 36 { 37 struct sigaction act = { 38 .sa_sigaction = segv_handler, 39 .sa_flags = SA_SIGINFO, 40 }; 41 char c, *p = NULL; 42 43 p = mmap(NULL, getpagesize(), 0, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 44 FAIL_IF(p == MAP_FAILED); 45 46 FAIL_IF(sigaction(SIGSEGV, &act, NULL) != 0); 47 48 faulted = false; 49 si_code = 0; 50 51 /* 52 * We just need a compiler barrier, but mb() works and has the nice 53 * property of being easy to spot in the disassembly. 54 */ 55 mb(); 56 c = *p; 57 mb(); 58 59 FAIL_IF(!faulted); 60 FAIL_IF(si_code != SEGV_ACCERR); 61 62 faulted = false; 63 si_code = 0; 64 65 mb(); 66 *p = c; 67 mb(); 68 69 FAIL_IF(!faulted); 70 FAIL_IF(si_code != SEGV_ACCERR); 71 72 return 0; 73 } 74 75 int main(void) 76 { 77 return test_harness(test_segv_errors, "segv_errors"); 78 } 79