segv_errors.c (1384B)
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 22static bool faulted; 23static int si_code; 24 25static 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 35int 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 75int main(void) 76{ 77 return test_harness(test_segv_errors, "segv_errors"); 78}