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 28 #include <sys/mman.h> 29 30 #include <atf-c.h> 31 #include <fcntl.h> 32 #include <setjmp.h> 33 #include <signal.h> 34 #include <stdio.h> 35 36 static sigjmp_buf sig_env; 37 static volatile int last_sig, last_code; 38 39 static void 40 sighandler(int sig, siginfo_t *info, void *context __unused) 41 { 42 43 last_sig = sig; 44 last_code = info->si_code; 45 siglongjmp(sig_env, 1); 46 } 47 48 static void 49 setup_signals(void) 50 { 51 struct sigaction sa; 52 int r; 53 54 sa.sa_sigaction = sighandler; 55 sa.sa_flags = SA_RESTART | SA_RESETHAND | SA_SIGINFO; 56 r = sigfillset(&sa.sa_mask); 57 ATF_REQUIRE(r != -1); 58 r = sigaction(SIGILL, &sa, NULL); 59 ATF_REQUIRE(r != -1); 60 r = sigaction(SIGBUS, &sa, NULL); 61 ATF_REQUIRE(r != -1); 62 r = sigaction(SIGSEGV, &sa, NULL); 63 ATF_REQUIRE(r != -1); 64 } 65 66 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_maperr_1); 67 ATF_TC_BODY(page_fault_signal__segv_maperr_1, tc) 68 { 69 int *p; 70 int r; 71 int sz; 72 73 sz = getpagesize(); 74 p = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0); 75 ATF_REQUIRE(p != MAP_FAILED); 76 r = munmap(p, sz); 77 ATF_REQUIRE(r != -1); 78 if (sigsetjmp(sig_env, 1) == 0) { 79 setup_signals(); 80 *(volatile int *)p = 1; 81 } 82 ATF_CHECK_EQ(SIGSEGV, last_sig); 83 ATF_CHECK_EQ(SEGV_MAPERR, last_code); 84 } 85 86 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_accerr_1); 87 ATF_TC_BODY(page_fault_signal__segv_accerr_1, tc) 88 { 89 int *p; 90 int sz; 91 92 sz = getpagesize(); 93 p = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0); 94 ATF_REQUIRE(p != MAP_FAILED); 95 if (sigsetjmp(sig_env, 1) == 0) { 96 setup_signals(); 97 *(volatile int *)p = 1; 98 } 99 (void)munmap(p, sz); 100 ATF_CHECK_EQ(SIGSEGV, last_sig); 101 ATF_CHECK_EQ(SEGV_ACCERR, last_code); 102 } 103 104 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_accerr_2); 105 ATF_TC_BODY(page_fault_signal__segv_accerr_2, tc) 106 { 107 int *p; 108 int sz; 109 110 sz = getpagesize(); 111 p = mmap(NULL, sz, PROT_NONE, MAP_ANON, -1, 0); 112 ATF_REQUIRE(p != MAP_FAILED); 113 if (sigsetjmp(sig_env, 1) == 0) { 114 setup_signals(); 115 (void)*(volatile int *)p; 116 } 117 (void)munmap(p, sz); 118 ATF_CHECK_EQ(SIGSEGV, last_sig); 119 ATF_CHECK_EQ(SEGV_ACCERR, last_code); 120 } 121 122 ATF_TC_WITHOUT_HEAD(page_fault_signal__bus_objerr_1); 123 ATF_TC_BODY(page_fault_signal__bus_objerr_1, tc) 124 { 125 int *p; 126 int fd; 127 int sz; 128 129 sz = getpagesize(); 130 fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, 0600); 131 ATF_REQUIRE(fd != -1); 132 p = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 133 ATF_REQUIRE(p != MAP_FAILED); 134 if (sigsetjmp(sig_env, 1) == 0) { 135 setup_signals(); 136 *(volatile int *)p = 1; 137 } 138 (void)munmap(p, sz); 139 (void)close(fd); 140 ATF_CHECK_EQ(SIGBUS, last_sig); 141 ATF_CHECK_EQ(BUS_OBJERR, last_code); 142 } 143 144 ATF_TC_WITHOUT_HEAD(page_fault_signal__bus_objerr_2); 145 ATF_TC_BODY(page_fault_signal__bus_objerr_2, tc) 146 { 147 int *p; 148 int fd; 149 int r; 150 int sz; 151 152 sz = getpagesize(); 153 fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, 0600); 154 ATF_REQUIRE(fd != -1); 155 r = ftruncate(fd, sz); 156 ATF_REQUIRE(r != -1); 157 p = mmap(NULL, sz * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 158 ATF_REQUIRE(p != MAP_FAILED); 159 if (sigsetjmp(sig_env, 1) == 0) { 160 setup_signals(); 161 ((volatile int *)p)[sz / sizeof(int)] = 1; 162 } 163 (void)munmap(p, sz * 2); 164 (void)close(fd); 165 ATF_CHECK_EQ(SIGBUS, last_sig); 166 ATF_CHECK_EQ(BUS_OBJERR, last_code); 167 } 168 169 ATF_TP_ADD_TCS(tp) 170 { 171 172 ATF_TP_ADD_TC(tp, page_fault_signal__segv_maperr_1); 173 ATF_TP_ADD_TC(tp, page_fault_signal__segv_accerr_1); 174 ATF_TP_ADD_TC(tp, page_fault_signal__segv_accerr_2); 175 ATF_TP_ADD_TC(tp, page_fault_signal__bus_objerr_1); 176 ATF_TP_ADD_TC(tp, page_fault_signal__bus_objerr_2); 177 178 return (atf_no_error()); 179 } 180