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 80 #define TEMPFILE "mmapfile" 81 82 char *TCID = "munmap02"; 83 int TST_TOTAL = 1; 84 85 static size_t page_sz; 86 char *addr; /* addr of memory mapped region */ 87 int fildes; /* file descriptor for tempfile */ 88 unsigned int map_len; /* length of the region to be mapped */ 89 90 void setup(); /* Main setup function of test */ 91 void cleanup(); /* cleanup function for the test */ 92 void sig_handler(); /* signal catching function */ 93 94 #ifndef UCLINUX 95 96 int main(int ac, char **av) 97 { 98 int lc; 99 100 tst_parse_opts(ac, av, NULL, NULL); 101 102 for (lc = 0; TEST_LOOPING(lc); lc++) { 103 104 tst_count = 0; 105 106 setup(); 107 108 /* 109 * Call munmap to unmap the part of the mapped region of the 110 * temporary file from the address and length that is part of 111 * the mapped region. 112 */ 113 TEST(munmap(addr, map_len)); 114 115 /* Check for the return value of munmap() */ 116 if (TEST_RETURN == -1) { 117 tst_resm(TFAIL, "munmap() fails, errno=%d : %s", 118 TEST_ERRNO, strerror(TEST_ERRNO)); 119 continue; 120 } 121 /* 122 * Check whether further reference is possible 123 * to the unmapped memory region by writing 124 * to the first byte of region with 125 * some arbitrary number. 126 */ 127 *addr = 50; 128 129 /* This message is printed if no SIGSEGV */ 130 tst_resm(TFAIL, "process succeeds to refer unmapped " 131 "memory region"); 132 cleanup(); 133 134 } 135 tst_exit(); 136 } 137 138 #else 139 140 int main(void) 141 { 142 tst_resm(TINFO, "munmap02 test is not available on uClinux"); 143 tst_exit(); 144 } 145 146 #endif /* ifndef UCLINUX */ 147 148 /* 149 * setup() - performs all ONE TIME setup for this test. 150 * Setup signal handler to catch SIGSEGV. 151 * Get system page size, create a temporary file for reading/writing, 152 * write one byte data into it, map the open file for the specified 153 * map length. 154 */ 155 void setup(void) 156 { 157 158 tst_sig(NOFORK, DEF_HANDLER, cleanup); 159 160 /* call signal function to trap the signal generated */ 161 if (signal(SIGSEGV, sig_handler) == SIG_ERR) { 162 tst_brkm(TBROK, cleanup, "signal fails to catch signal"); 163 } 164 165 TEST_PAUSE; 166 167 /* Get the system page size */ 168 page_sz = getpagesize(); 169 170 /* 171 * Get the length of the open file to be mapped into process 172 * address space. 173 */ 174 map_len = 3 * page_sz; 175 176 tst_tmpdir(); 177 178 /* Creat a temporary file used for mapping */ 179 if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) { 180 tst_brkm(TBROK, cleanup, "open() on %s Failed, errno=%d : %s", 181 TEMPFILE, errno, strerror(errno)); 182 } 183 184 /* 185 * move the file pointer to maplength position from the beginning 186 * of the file. 187 */ 188 if (lseek(fildes, map_len, SEEK_SET) == -1) { 189 tst_brkm(TBROK, cleanup, "lseek() fails on %s, errno=%d : %s", 190 TEMPFILE, errno, strerror(errno)); 191 } 192 193 /* Write one byte into temporary file */ 194 if (write(fildes, "a", 1) != 1) { 195 tst_brkm(TBROK, cleanup, "write() on %s Failed, errno=%d : %s", 196 TEMPFILE, errno, strerror(errno)); 197 } 198 199 /* 200 * map the open file 'TEMPFILE' from its beginning up to the maplength 201 * into the calling process's address space at the system choosen 202 * with read/write permissions to the the mapped region. 203 */ 204 #ifdef UCLINUX 205 /* mmap() doesn't support MAP_SHARED on uClinux */ 206 addr = mmap(0, map_len, PROT_READ | PROT_WRITE, 207 MAP_FILE | MAP_PRIVATE, fildes, 0); 208 #else 209 addr = mmap(0, map_len, PROT_READ | PROT_WRITE, 210 MAP_FILE | MAP_SHARED, fildes, 0); 211 #endif 212 213 /* check for the return value of mmap system call */ 214 if (addr == (char *)MAP_FAILED) { 215 tst_brkm(TBROK, cleanup, "mmap() Failed on %s, errno=%d : %s", 216 TEMPFILE, errno, strerror(errno)); 217 } 218 219 /* 220 * increment the start address of the region at which the file is 221 * mapped to a maplength of 3 times the system page size by the value 222 * of system page size and decrement the maplength value by the value 223 * of system page size. 224 */ 225 addr = (char *)((long)addr + page_sz); 226 map_len = map_len - page_sz; 227 } 228 229 /* 230 * void 231 * sig_handler() - signal catching function. 232 * This function is used to trap the signal generated when tried to read or 233 * write to the memory mapped region which is already detached from the 234 * calling process address space. 235 * this function is invoked when SIGSEGV generated and it calls test 236 * cleanup function and exit the program. 237 */ 238 void sig_handler(void) 239 { 240 tst_resm(TPASS, "Functionality of munmap() successful"); 241 242 /* Invoke test cleanup function and exit */ 243 cleanup(); 244 245 tst_exit(); 246 } 247 248 /* 249 * cleanup() - performs all ONE TIME cleanup for this test at 250 * completion or premature exit. 251 * Unmap the portion of the region of the file left unmapped. 252 * Close the temporary file. 253 * Remove the temporary directory. 254 */ 255 void cleanup(void) 256 { 257 258 /* 259 * get the start address and length of the portion of 260 * the mapped region of the file. 261 */ 262 addr = (char *)((long)addr - page_sz); 263 map_len = map_len - page_sz; 264 265 /* unmap the portion of the region of the file left unmapped */ 266 if (munmap(addr, map_len) < 0) { 267 tst_brkm(TBROK, NULL, 268 "munmap() fails to unmap portion of mapped region"); 269 } 270 271 /* Close the temporary file */ 272 if (close(fildes) < 0) { 273 tst_brkm(TBROK, NULL, "close() on %s Failed, errno=%d : %s", 274 TEMPFILE, errno, strerror(errno)); 275 } 276 277 tst_rmdir(); 278 } 279