1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* 20 * DESCRIPTION 21 * Testcase to check the mprotect(2) system call. 22 * 23 * ALGORITHM 24 * Create a mapped region using mmap with READ permission. 25 * Try to write into that region in a child process using memcpy. 26 * Verify that a SIGSEGV is generated. 27 * Now change the protection to WRITE using mprotect(2). 28 * Again try to write into the mapped region. 29 * Verify that no SIGSEGV is generated. 30 * 31 * HISTORY 32 * 07/2001 Ported by Wayne Boyer 33 * 05/2002 changed over to use tst_sig instead of sigaction 34 */ 35 36 #include <sys/mman.h> 37 #include <sys/wait.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <limits.h> 41 #include <stdlib.h> 42 #include "test.h" 43 44 #include "safe_macros.h" 45 46 static void sighandler(int sig); 47 static void cleanup(void); 48 static void setup(void); 49 50 char *TCID = "mprotect02"; 51 int TST_TOTAL = 1; 52 static int fd, status; 53 static char file1[BUFSIZ]; 54 55 static char *addr = MAP_FAILED; 56 static char buf[] = "abcdefghijklmnopqrstuvwxyz"; 57 58 int main(int ac, char **av) 59 { 60 int lc; 61 62 int bytes_to_write, fd; 63 unsigned int num_bytes; 64 pid_t pid; 65 66 tst_parse_opts(ac, av, NULL, NULL); 67 68 setup(); 69 70 for (lc = 0; TEST_LOOPING(lc); lc++) { 71 72 tst_count = 0; 73 74 fd = SAFE_OPEN(cleanup, file1, O_RDWR | O_CREAT, 0777); 75 76 num_bytes = getpagesize(); 77 78 do { 79 80 bytes_to_write = MIN(strlen(buf), num_bytes); 81 82 num_bytes -= 83 SAFE_WRITE(cleanup, 1, fd, buf, bytes_to_write); 84 85 } while (0 < num_bytes); 86 87 /* mmap the PAGESIZE bytes as read only. */ 88 addr = SAFE_MMAP(cleanup, 0, sizeof(buf), PROT_READ, 89 MAP_SHARED, fd, 0); 90 91 if ((pid = FORK_OR_VFORK()) == -1) 92 tst_brkm(TBROK | TERRNO, cleanup, "fork #1 failed"); 93 94 if (pid == 0) { 95 memcpy(addr, buf, strlen(buf)); 96 exit(255); 97 } 98 99 SAFE_WAITPID(cleanup, pid, &status, 0); 100 if (!WIFEXITED(status)) 101 tst_brkm(TBROK, cleanup, "child exited abnormally " 102 "with status: %d", status); 103 switch (status) { 104 case 255: 105 tst_brkm(TBROK, cleanup, 106 "memcpy did not generate SIGSEGV"); 107 case 0: 108 tst_resm(TPASS, "got SIGSEGV as expected"); 109 break; 110 default: 111 tst_brkm(TBROK, cleanup, "got unexpected signal: %d", 112 status); 113 break; 114 } 115 116 /* Change the protection to WRITE. */ 117 TEST(mprotect(addr, sizeof(buf), PROT_WRITE)); 118 119 if (TEST_RETURN != -1) { 120 if ((pid = FORK_OR_VFORK()) == -1) 121 tst_brkm(TBROK | TERRNO, cleanup, 122 "fork #2 failed"); 123 124 if (pid == 0) { 125 memcpy(addr, buf, strlen(buf)); 126 exit(0); 127 } 128 129 SAFE_WAITPID(cleanup, pid, &status, 0); 130 131 if (WIFEXITED(status) && 132 WEXITSTATUS(status) == 0) 133 tst_resm(TPASS, "didn't get SIGSEGV"); 134 else 135 tst_brkm(TBROK, cleanup, 136 "child exited abnormally"); 137 } else { 138 tst_resm(TFAIL | TERRNO, "mprotect failed"); 139 continue; 140 } 141 142 SAFE_MUNMAP(cleanup, addr, sizeof(buf)); 143 addr = MAP_FAILED; 144 145 SAFE_CLOSE(cleanup, fd); 146 147 SAFE_UNLINK(cleanup, file1); 148 149 } 150 151 cleanup(); 152 tst_exit(); 153 } 154 155 static void sighandler(int sig) 156 { 157 _exit((sig == SIGSEGV) ? 0 : sig); 158 } 159 160 static void setup(void) 161 { 162 tst_sig(FORK, sighandler, cleanup); 163 164 TEST_PAUSE; 165 166 tst_tmpdir(); 167 168 sprintf(file1, "mprotect02.tmp.%d", getpid()); 169 } 170 171 static void cleanup(void) 172 { 173 if (addr != MAP_FAILED) { 174 SAFE_MUNMAP(NULL, addr, sizeof(buf)); 175 SAFE_CLOSE(NULL, fd); 176 } 177 178 tst_rmdir(); 179 } 180