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 * NAME 21 * mprotect03.c 22 * 23 * DESCRIPTION 24 * Testcase to check the mprotect(2) system call. 25 * 26 * ALGORITHM 27 * Create a shared mapped file region with PROT_READ | PROT_WRITE 28 * using the mmap(2) call. Then, use mprotect(2) to disable the 29 * write permission on the mapped region. Then, attempt to write to 30 * the mapped region using memcpy(). This would generate a sigsegv. 31 * Since the sigsegv is generated, this needs to be done in a child 32 * process (as sigsegv would repeatedly be generated). The testcase 33 * succeeds only when this sigsegv is generated while attempting to 34 * memcpy() on a shared region with only read permission. 35 * 36 * HISTORY 37 * 07/2001 Ported by Wayne Boyer 38 * 05/2002 changed over to use tst_sig instead of sigaction 39 */ 40 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <sys/mman.h> 44 #include <limits.h> 45 #include <signal.h> 46 #include <sys/wait.h> 47 #include "test.h" 48 49 #include "safe_macros.h" 50 51 #ifndef PAGESIZE 52 #define PAGESIZE 4096 53 #endif 54 #define FAILED 1 55 56 static void cleanup(void); 57 static void setup(void); 58 59 char *TCID = "mprotect03"; 60 int TST_TOTAL = 1; 61 int status; 62 char file1[BUFSIZ]; 63 64 int main(int ac, char **av) 65 { 66 int lc; 67 68 char *addr; 69 int fd, pid; 70 char *buf = "abcdefghijklmnopqrstuvwxyz"; 71 72 tst_parse_opts(ac, av, NULL, NULL); 73 74 setup(); 75 76 for (lc = 0; TEST_LOOPING(lc); lc++) { 77 tst_count = 0; 78 79 if ((fd = open(file1, O_RDWR | O_CREAT, 0777)) < 0) 80 tst_brkm(TBROK, cleanup, "open failed"); 81 82 SAFE_WRITE(cleanup, 1, fd, buf, strlen(buf)); 83 84 /* 85 * mmap the PAGESIZE bytes as read only. 86 */ 87 addr = mmap(0, strlen(buf), PROT_READ | PROT_WRITE, MAP_SHARED, 88 fd, 0); 89 if (addr == MAP_FAILED) 90 tst_brkm(TBROK, cleanup, "mmap failed"); 91 92 /* 93 * Try to change the protection to WRITE. 94 */ 95 TEST(mprotect(addr, strlen(buf), PROT_READ)); 96 97 if (TEST_RETURN != -1) { 98 if ((pid = FORK_OR_VFORK()) == -1) { 99 tst_brkm(TBROK, cleanup, "fork failed"); 100 } 101 102 if (pid == 0) { 103 memcpy(addr, buf, strlen(buf)); 104 tst_resm(TINFO, "memcpy() did " 105 "not generate SIGSEGV"); 106 exit(1); 107 } 108 109 waitpid(pid, &status, 0); 110 if (WEXITSTATUS(status) != 0) { 111 tst_resm(TFAIL, "child returned " 112 "unexpected status"); 113 } else { 114 tst_resm(TPASS, "SIGSEGV generated " 115 "as expected"); 116 } 117 } else { 118 tst_resm(TFAIL, "mprotect failed " 119 "unexpectedly, errno: %d", errno); 120 } 121 122 /* clean up things in case we are looping */ 123 SAFE_MUNMAP(cleanup, addr, strlen(buf)); 124 SAFE_CLOSE(cleanup, fd); 125 SAFE_UNLINK(cleanup, file1); 126 } 127 128 cleanup(); 129 tst_exit(); 130 } 131 132 static void sighandler(int sig) 133 { 134 if (sig == SIGSEGV) { 135 tst_resm(TINFO, "received signal: SIGSEGV"); 136 tst_exit(); 137 } else 138 tst_brkm(TBROK, 0, "Unexpected signal %d received.", sig); 139 } 140 141 static void setup(void) 142 { 143 tst_sig(FORK, sighandler, NULL); 144 145 TEST_PAUSE; 146 147 tst_tmpdir(); 148 149 sprintf(file1, "mprotect03.tmp.%d", getpid()); 150 } 151 152 static void cleanup(void) 153 { 154 tst_rmdir(); 155 } 156