1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2019 Jilles Tjoelker 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include <sys/mman.h> 31 32 #include <atf-c.h> 33 #include <fcntl.h> 34 #include <setjmp.h> 35 #include <signal.h> 36 #include <stdio.h> 37 38 static sigjmp_buf sig_env; 39 static volatile int last_sig, last_code; 40 41 static void 42 sighandler(int sig, siginfo_t *info, void *context __unused) 43 { 44 45 last_sig = sig; 46 last_code = info->si_code; 47 siglongjmp(sig_env, 1); 48 } 49 50 static void 51 setup_signals(void) 52 { 53 struct sigaction sa; 54 int r; 55 56 sa.sa_sigaction = sighandler; 57 sa.sa_flags = SA_RESTART | SA_RESETHAND | SA_SIGINFO; 58 r = sigfillset(&sa.sa_mask); 59 ATF_REQUIRE(r != -1); 60 r = sigaction(SIGILL, &sa, NULL); 61 ATF_REQUIRE(r != -1); 62 r = sigaction(SIGBUS, &sa, NULL); 63 ATF_REQUIRE(r != -1); 64 r = sigaction(SIGSEGV, &sa, NULL); 65 ATF_REQUIRE(r != -1); 66 } 67 68 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_maperr_1); 69 ATF_TC_BODY(page_fault_signal__segv_maperr_1, tc) 70 { 71 int *p; 72 int r; 73 int sz; 74 75 sz = getpagesize(); 76 p = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0); 77 ATF_REQUIRE(p != MAP_FAILED); 78 r = munmap(p, sz); 79 ATF_REQUIRE(r != -1); 80 if (sigsetjmp(sig_env, 1) == 0) { 81 setup_signals(); 82 *(volatile int *)p = 1; 83 } 84 ATF_CHECK_EQ(SIGSEGV, last_sig); 85 ATF_CHECK_EQ(SEGV_MAPERR, last_code); 86 } 87 88 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_accerr_1); 89 ATF_TC_BODY(page_fault_signal__segv_accerr_1, tc) 90 { 91 int *p; 92 int sz; 93 94 sz = getpagesize(); 95 p = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0); 96 ATF_REQUIRE(p != MAP_FAILED); 97 if (sigsetjmp(sig_env, 1) == 0) { 98 setup_signals(); 99 *(volatile int *)p = 1; 100 } 101 (void)munmap(p, sz); 102 ATF_CHECK_EQ(SIGSEGV, last_sig); 103 ATF_CHECK_EQ(SEGV_ACCERR, last_code); 104 } 105 106 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_accerr_2); 107 ATF_TC_BODY(page_fault_signal__segv_accerr_2, tc) 108 { 109 int *p; 110 int sz; 111 112 sz = getpagesize(); 113 p = mmap(NULL, sz, PROT_NONE, MAP_ANON, -1, 0); 114 ATF_REQUIRE(p != MAP_FAILED); 115 if (sigsetjmp(sig_env, 1) == 0) { 116 setup_signals(); 117 (void)*(volatile int *)p; 118 } 119 (void)munmap(p, sz); 120 ATF_CHECK_EQ(SIGSEGV, last_sig); 121 ATF_CHECK_EQ(SEGV_ACCERR, last_code); 122 } 123 124 ATF_TC_WITHOUT_HEAD(page_fault_signal__bus_objerr_1); 125 ATF_TC_BODY(page_fault_signal__bus_objerr_1, tc) 126 { 127 int *p; 128 int fd; 129 int sz; 130 131 sz = getpagesize(); 132 fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, 0600); 133 ATF_REQUIRE(fd != -1); 134 p = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 135 ATF_REQUIRE(p != MAP_FAILED); 136 if (sigsetjmp(sig_env, 1) == 0) { 137 setup_signals(); 138 *(volatile int *)p = 1; 139 } 140 (void)munmap(p, sz); 141 (void)close(fd); 142 ATF_CHECK_EQ(SIGBUS, last_sig); 143 ATF_CHECK_EQ(BUS_OBJERR, last_code); 144 } 145 146 ATF_TC_WITHOUT_HEAD(page_fault_signal__bus_objerr_2); 147 ATF_TC_BODY(page_fault_signal__bus_objerr_2, tc) 148 { 149 int *p; 150 int fd; 151 int r; 152 int sz; 153 154 sz = getpagesize(); 155 fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, 0600); 156 ATF_REQUIRE(fd != -1); 157 r = ftruncate(fd, sz); 158 ATF_REQUIRE(r != -1); 159 p = mmap(NULL, sz * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 160 ATF_REQUIRE(p != MAP_FAILED); 161 if (sigsetjmp(sig_env, 1) == 0) { 162 setup_signals(); 163 ((volatile int *)p)[sz / sizeof(int)] = 1; 164 } 165 (void)munmap(p, sz * 2); 166 (void)close(fd); 167 ATF_CHECK_EQ(SIGBUS, last_sig); 168 ATF_CHECK_EQ(BUS_OBJERR, last_code); 169 } 170 171 ATF_TP_ADD_TCS(tp) 172 { 173 174 ATF_TP_ADD_TC(tp, page_fault_signal__segv_maperr_1); 175 ATF_TP_ADD_TC(tp, page_fault_signal__segv_accerr_1); 176 ATF_TP_ADD_TC(tp, page_fault_signal__segv_accerr_2); 177 ATF_TP_ADD_TC(tp, page_fault_signal__bus_objerr_1); 178 ATF_TP_ADD_TC(tp, page_fault_signal__bus_objerr_2); 179 180 return (atf_no_error()); 181 } 182