1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * Test Name: munmap01 22 * 23 * Test Description: 24 * Verify that, munmap call will succeed to unmap a mapped file or 25 * anonymous shared memory region from the calling process's address space 26 * and after successful completion of munmap, the unmapped region is no 27 * longer accessible. 28 * 29 * Expected Result: 30 * munmap call should succeed to unmap a mapped file or anonymous shared 31 * memory region from the process's address space and it returns with a 32 * value 0, further reference to the unmapped region should result in a 33 * segmentation fault (SIGSEGV). 34 * 35 * Algorithm: 36 * Setup: 37 * Setup signal handling. 38 * Create temporary directory. 39 * Pause for SIGUSR1 if option specified. 40 * 41 * Test: 42 * Loop if the proper options are given. 43 * Execute system call 44 * Check return code, if system call failed (return=-1) 45 * Log the errno and Issue a FAIL message. 46 * Otherwise, 47 * Verify the Functionality of system call 48 * if successful, 49 * Issue Functionality-Pass message. 50 * Otherwise, 51 * Issue Functionality-Fail message. 52 * Cleanup: 53 * Print errno log and/or timing stats if options given 54 * Delete the temporary directory created. 55 * 56 * Usage: <for command-line> 57 * munmap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 58 * where, -c n : Run n copies concurrently. 59 * -f : Turn off functionality Testing. 60 * -i n : Execute test n times. 61 * -I x : Execute test for x seconds. 62 * -P x : Pause for x seconds between iterations. 63 * -t : Turn on syscall timing. 64 * 65 * HISTORY 66 * 07/2001 Ported by Wayne Boyer 67 * 68 * RESTRICTIONS: 69 * None.$ 70 */ 71 #include <errno.h> 72 #include <unistd.h> 73 #include <fcntl.h> 74 #include <sys/stat.h> 75 #include <sys/mman.h> 76 77 #include "test.h" 78 #include "safe_macros.h" 79 80 #define TEMPFILE "mmapfile" 81 82 char *TCID = "munmap01"; 83 int TST_TOTAL = 1; 84 85 char *addr; /* addr of memory mapped region */ 86 int fildes; /* file descriptor for tempfile */ 87 unsigned int map_len; /* length of the region to be mapped */ 88 89 void setup(); /* Main setup function of test */ 90 void cleanup(); /* cleanup function for the test */ 91 void sig_handler(); /* signal catching function */ 92 93 int main(int ac, char **av) 94 { 95 int lc; 96 97 tst_parse_opts(ac, av, NULL, NULL); 98 99 for (lc = 0; TEST_LOOPING(lc); lc++) { 100 101 tst_count = 0; 102 103 setup(); 104 105 /* 106 * Call munmap to unmap the mapped region of the 107 * temporary file from the calling process's address space. 108 */ 109 TEST(munmap(addr, map_len)); 110 111 /* Check for the return value of munmap() */ 112 if (TEST_RETURN == -1) { 113 tst_resm(TFAIL, "munmap() fails, errno=%d : %s", 114 TEST_ERRNO, strerror(TEST_ERRNO)); 115 continue; 116 } 117 #ifdef UCLINUX 118 /* 119 * No SIGSEGV on uClinux since 120 * MMU not implemented on uClinux 121 */ 122 tst_resm(TPASS, "call succedded"); 123 #else 124 /* 125 * Check whether further reference is possible 126 * to the unmapped memory region by writing 127 * to the first byte of region with 128 * some arbitrary number. 129 */ 130 *addr = 50; 131 132 /* This message is printed if no SIGSEGV */ 133 tst_resm(TFAIL, "process succeeds to refer unmapped " 134 "memory region"); 135 #endif 136 137 cleanup(); 138 139 } 140 tst_exit(); 141 } 142 143 /* 144 * setup() - performs all ONE TIME setup for this test. 145 * 146 * Set up signal handler to catch SIGSEGV. 147 * Get system page size, create a temporary file for reading/writing, 148 * write one byte data into it, map the open file for the specified 149 * map length. 150 */ 151 void setup(void) 152 { 153 size_t page_sz; 154 155 tst_sig(NOFORK, DEF_HANDLER, cleanup); 156 157 /* call signal function to trap the signal generated */ 158 if (signal(SIGSEGV, sig_handler) == SIG_ERR) { 159 tst_brkm(TBROK, cleanup, "signal fails to catch signal"); 160 } 161 162 TEST_PAUSE; 163 164 /* Get the system page size */ 165 page_sz = getpagesize(); 166 167 /* 168 * Get the length of the open file to be mapped into process 169 * address space. 170 */ 171 map_len = 3 * page_sz; 172 173 tst_tmpdir(); 174 175 /* Creat a temporary file used for mapping */ 176 if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) { 177 tst_brkm(TBROK, cleanup, "open() on %s Failed, errno=%d : %s", 178 TEMPFILE, errno, strerror(errno)); 179 } 180 181 /* 182 * move the file pointer to maplength position from the beginning 183 * of the file. 184 */ 185 SAFE_LSEEK(cleanup, fildes, map_len, SEEK_SET); 186 187 /* Write one byte into temporary file */ 188 if (write(fildes, "a", 1) != 1) { 189 tst_brkm(TBROK, cleanup, "write() on %s Failed, errno=%d : %s", 190 TEMPFILE, errno, strerror(errno)); 191 } 192 193 /* 194 * map the open file 'TEMPFILE' from its beginning up to the maplength 195 * into the calling process's address space at the system choosen 196 * with read/write permissions to the the mapped region. 197 */ 198 #ifdef UCLINUX 199 /* MAP_SHARED is not implemented on uClinux */ 200 addr = mmap(0, map_len, PROT_READ | PROT_WRITE, 201 MAP_FILE | MAP_PRIVATE, fildes, 0); 202 #else 203 addr = mmap(0, map_len, PROT_READ | PROT_WRITE, 204 MAP_FILE | MAP_SHARED, fildes, 0); 205 #endif 206 207 /* check for the return value of mmap system call */ 208 if (addr == (char *)MAP_FAILED) { 209 tst_brkm(TBROK, cleanup, "mmap() Failed on %s, errno=%d : %s", 210 TEMPFILE, errno, strerror(errno)); 211 } 212 213 } 214 215 /* 216 * sig_handler() - signal catching function. 217 * This function is used to trap the signal generated when tried to read or 218 * write to the memory mapped region which is already detached from the 219 * calling process address space. 220 * this function is invoked when SIGSEGV generated and it calls test 221 * cleanup function and exit the program. 222 */ 223 void sig_handler(void) 224 { 225 tst_resm(TPASS, "Functionality of munmap() successful"); 226 227 /* Invoke test cleanup function and exit */ 228 cleanup(); 229 230 tst_exit(); 231 } 232 233 /* 234 * cleanup() - performs all ONE TIME cleanup for this test at 235 * completion or premature exit. 236 * Close the temporary file. 237 * Remove the temporary directory. 238 */ 239 void cleanup(void) 240 { 241 242 /* Close the temporary file */ 243 if (close(fildes) < 0) { 244 tst_brkm(TFAIL, NULL, "close() on %s Failed, errno=%d : %s", 245 TEMPFILE, errno, strerror(errno)); 246 } 247 248 tst_rmdir(); 249 } 250