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: munmap02 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 * if the region specified by the address and the length is part or all of 27 * the mapped region. 28 * 29 * Expected Result: 30 * munmap call should succeed to unmap a part or all of mapped region of a 31 * file or anonymous shared memory from the process's address space and it 32 * returns with a value 0, 33 * further reference to the unmapped region should result in a segmentation 34 * fault (SIGSEGV). 35 * 36 * Algorithm: 37 * Setup: 38 * Setup signal handling. 39 * Create temporary directory. 40 * Pause for SIGUSR1 if option specified. 41 * 42 * Test: 43 * Loop if the proper options are given. 44 * Execute system call 45 * Check return code, if system call failed (return=-1) 46 * Log the errno and Issue a FAIL message. 47 * Otherwise, 48 * Verify the Functionality of system call 49 * if successful, 50 * Issue Functionality-Pass message. 51 * Otherwise, 52 * Issue Functionality-Fail message. 53 * Cleanup: 54 * Print errno log and/or timing stats if options given 55 * Delete the temporary directory created. 56 * 57 * Usage: <for command-line> 58 * munmap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 59 * where, -c n : Run n copies concurrently. 60 * -f : Turn off functionality Testing. 61 * -i n : Execute test n times. 62 * -I x : Execute test for x seconds. 63 * -P x : Pause for x seconds between iterations. 64 * -t : Turn on syscall timing. 65 * 66 * HISTORY 67 * 07/2001 Ported by Wayne Boyer 68 * 69 * RESTRICTIONS: 70 * None. 71 */ 72 #include <errno.h> 73 #include <unistd.h> 74 #include <fcntl.h> 75 #include <sys/stat.h> 76 #include <sys/mman.h> 77 78 #include "test.h" 79 #include "safe_macros.h" 80 81 #define TEMPFILE "mmapfile" 82 83 char *TCID = "munmap02"; 84 int TST_TOTAL = 1; 85 86 static size_t page_sz; 87 char *addr; /* addr of memory mapped region */ 88 int fildes; /* file descriptor for tempfile */ 89 unsigned int map_len; /* length of the region to be mapped */ 90 91 void setup(); /* Main setup function of test */ 92 void cleanup(); /* cleanup function for the test */ 93 void sig_handler(); /* signal catching function */ 94 95 #ifndef UCLINUX 96 97 int main(int ac, char **av) 98 { 99 int lc; 100 101 tst_parse_opts(ac, av, NULL, NULL); 102 103 for (lc = 0; TEST_LOOPING(lc); lc++) { 104 105 tst_count = 0; 106 107 setup(); 108 109 /* 110 * Call munmap to unmap the part of the mapped region of the 111 * temporary file from the address and length that is part of 112 * the mapped region. 113 */ 114 TEST(munmap(addr, map_len)); 115 116 /* Check for the return value of munmap() */ 117 if (TEST_RETURN == -1) { 118 tst_resm(TFAIL, "munmap() fails, errno=%d : %s", 119 TEST_ERRNO, strerror(TEST_ERRNO)); 120 continue; 121 } 122 /* 123 * Check whether further reference is possible 124 * to the unmapped memory region by writing 125 * to the first byte of region with 126 * some arbitrary number. 127 */ 128 *addr = 50; 129 130 /* This message is printed if no SIGSEGV */ 131 tst_resm(TFAIL, "process succeeds to refer unmapped " 132 "memory region"); 133 cleanup(); 134 135 } 136 tst_exit(); 137 } 138 139 #else 140 141 int main(void) 142 { 143 tst_resm(TINFO, "munmap02 test is not available on uClinux"); 144 tst_exit(); 145 } 146 147 #endif /* ifndef UCLINUX */ 148 149 /* 150 * setup() - performs all ONE TIME setup for this test. 151 * Setup signal handler to catch SIGSEGV. 152 * Get system page size, create a temporary file for reading/writing, 153 * write one byte data into it, map the open file for the specified 154 * map length. 155 */ 156 void setup(void) 157 { 158 159 tst_sig(NOFORK, DEF_HANDLER, cleanup); 160 161 /* call signal function to trap the signal generated */ 162 if (signal(SIGSEGV, sig_handler) == SIG_ERR) { 163 tst_brkm(TBROK, cleanup, "signal fails to catch signal"); 164 } 165 166 TEST_PAUSE; 167 168 /* Get the system page size */ 169 page_sz = getpagesize(); 170 171 /* 172 * Get the length of the open file to be mapped into process 173 * address space. 174 */ 175 map_len = 3 * page_sz; 176 177 tst_tmpdir(); 178 179 /* Creat a temporary file used for mapping */ 180 if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) { 181 tst_brkm(TBROK, cleanup, "open() on %s Failed, errno=%d : %s", 182 TEMPFILE, errno, strerror(errno)); 183 } 184 185 /* 186 * move the file pointer to maplength position from the beginning 187 * of the file. 188 */ 189 SAFE_LSEEK(cleanup, fildes, map_len, SEEK_SET); 190 191 /* Write one byte into temporary file */ 192 if (write(fildes, "a", 1) != 1) { 193 tst_brkm(TBROK, cleanup, "write() on %s Failed, errno=%d : %s", 194 TEMPFILE, errno, strerror(errno)); 195 } 196 197 /* 198 * map the open file 'TEMPFILE' from its beginning up to the maplength 199 * into the calling process's address space at the system choosen 200 * with read/write permissions to the the mapped region. 201 */ 202 #ifdef UCLINUX 203 /* mmap() doesn't support MAP_SHARED on uClinux */ 204 addr = mmap(0, map_len, PROT_READ | PROT_WRITE, 205 MAP_FILE | MAP_PRIVATE, fildes, 0); 206 #else 207 addr = mmap(0, map_len, PROT_READ | PROT_WRITE, 208 MAP_FILE | MAP_SHARED, fildes, 0); 209 #endif 210 211 /* check for the return value of mmap system call */ 212 if (addr == (char *)MAP_FAILED) { 213 tst_brkm(TBROK, cleanup, "mmap() Failed on %s, errno=%d : %s", 214 TEMPFILE, errno, strerror(errno)); 215 } 216 217 /* 218 * increment the start address of the region at which the file is 219 * mapped to a maplength of 3 times the system page size by the value 220 * of system page size and decrement the maplength value by the value 221 * of system page size. 222 */ 223 addr = (char *)((long)addr + page_sz); 224 map_len = map_len - page_sz; 225 } 226 227 /* 228 * void 229 * sig_handler() - signal catching function. 230 * This function is used to trap the signal generated when tried to read or 231 * write to the memory mapped region which is already detached from the 232 * calling process address space. 233 * this function is invoked when SIGSEGV generated and it calls test 234 * cleanup function and exit the program. 235 */ 236 void sig_handler(void) 237 { 238 tst_resm(TPASS, "Functionality of munmap() successful"); 239 240 /* Invoke test cleanup function and exit */ 241 cleanup(); 242 243 tst_exit(); 244 } 245 246 /* 247 * cleanup() - performs all ONE TIME cleanup for this test at 248 * completion or premature exit. 249 * Unmap the portion of the region of the file left unmapped. 250 * Close the temporary file. 251 * Remove the temporary directory. 252 */ 253 void cleanup(void) 254 { 255 256 /* 257 * get the start address and length of the portion of 258 * the mapped region of the file. 259 */ 260 addr = (char *)((long)addr - page_sz); 261 map_len = map_len - page_sz; 262 263 /* unmap the portion of the region of the file left unmapped */ 264 SAFE_MUNMAP(NULL, addr, map_len); 265 266 /* Close the temporary file */ 267 SAFE_CLOSE(NULL, fildes); 268 269 tst_rmdir(); 270 } 271