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 46static void sighandler(int sig); 47static void cleanup(void); 48static void setup(void); 49 50char *TCID = "mprotect02"; 51int TST_TOTAL = 1; 52static int fd, status; 53static char file1[BUFSIZ]; 54 55static char *addr = MAP_FAILED; 56static char buf[] = "abcdefghijklmnopqrstuvwxyz"; 57 58int main(int ac, char **av) 59{ 60 int lc; 61 62 int bytes_to_write, fd; 63 size_t 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, SAFE_WRITE_ALL, fd, buf, 84 bytes_to_write); 85 86 } while (0 < num_bytes); 87 88 /* mmap the PAGESIZE bytes as read only. */ 89 addr = SAFE_MMAP(cleanup, 0, sizeof(buf), PROT_READ, 90 MAP_SHARED, fd, 0); 91 92 if ((pid = FORK_OR_VFORK()) == -1) 93 tst_brkm(TBROK | TERRNO, cleanup, "fork #1 failed"); 94 95 if (pid == 0) { 96 memcpy(addr, buf, strlen(buf)); 97 exit(255); 98 } 99 100 SAFE_WAITPID(cleanup, pid, &status, 0); 101 if (!WIFEXITED(status)) 102 tst_brkm(TBROK, cleanup, "child exited abnormally " 103 "with status: %d", status); 104 switch (status) { 105 case 255: 106 tst_brkm(TBROK, cleanup, 107 "memcpy did not generate SIGSEGV"); 108 case 0: 109 tst_resm(TPASS, "got SIGSEGV as expected"); 110 break; 111 default: 112 tst_brkm(TBROK, cleanup, "got unexpected signal: %d", 113 status); 114 break; 115 } 116 117 /* Change the protection to WRITE. */ 118 TEST(mprotect(addr, sizeof(buf), PROT_WRITE)); 119 120 if (TEST_RETURN != -1) { 121 if ((pid = FORK_OR_VFORK()) == -1) 122 tst_brkm(TBROK | TERRNO, cleanup, 123 "fork #2 failed"); 124 125 if (pid == 0) { 126 memcpy(addr, buf, strlen(buf)); 127 exit(0); 128 } 129 130 SAFE_WAITPID(cleanup, pid, &status, 0); 131 132 if (WIFEXITED(status) && 133 WEXITSTATUS(status) == 0) 134 tst_resm(TPASS, "didn't get SIGSEGV"); 135 else 136 tst_brkm(TBROK, cleanup, 137 "child exited abnormally"); 138 } else { 139 tst_resm(TFAIL | TERRNO, "mprotect failed"); 140 continue; 141 } 142 143 SAFE_MUNMAP(cleanup, addr, sizeof(buf)); 144 addr = MAP_FAILED; 145 146 SAFE_CLOSE(cleanup, fd); 147 148 SAFE_UNLINK(cleanup, file1); 149 150 } 151 152 cleanup(); 153 tst_exit(); 154} 155 156static void sighandler(int sig) 157{ 158 _exit((sig == SIGSEGV) ? 0 : sig); 159} 160 161static void setup(void) 162{ 163 tst_sig(FORK, sighandler, cleanup); 164 165 TEST_PAUSE; 166 167 tst_tmpdir(); 168 169 sprintf(file1, "mprotect02.tmp.%d", getpid()); 170} 171 172static void cleanup(void) 173{ 174 if (addr != MAP_FAILED) { 175 SAFE_MUNMAP(NULL, addr, sizeof(buf)); 176 SAFE_CLOSE(NULL, fd); 177 } 178 179 tst_rmdir(); 180} 181