1/*- 2 * Copyright (c) 2006 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/tests/sys/posixshm/posixshm_test.c 289441 2015-10-17 04:32:21Z ngie $"); |
29 30#include <sys/param.h> 31#include <sys/mman.h> 32#include <sys/resource.h> 33#include <sys/stat.h> 34#include <sys/syscall.h> 35#include <sys/wait.h> 36 --- 68 unchanged lines hidden (view full) --- 105 106 fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777); 107 if (fd < 0 && errno == EEXIST) { 108 if (shm_unlink(test_path) < 0) 109 atf_tc_fail("shm_unlink"); 110 fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 111 } 112 if (fd < 0) |
113 atf_tc_fail("shm_open failed; errno=%d", errno); |
114 if (ftruncate(fd, getpagesize()) < 0) |
115 atf_tc_fail("ftruncate failed; errno=%d", errno); |
116 117 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 118 0); 119 if (page == MAP_FAILED) |
120 atf_tc_fail("mmap failed; errno=%d", errno); |
121 122 page[0] = '1'; 123 if (munmap(page, getpagesize()) < 0) |
124 atf_tc_fail("munmap failed; errno=%d", errno); |
125 126 return (fd); 127} 128 129ATF_TC_WITHOUT_HEAD(remap_object); 130ATF_TC_BODY(remap_object, tc) 131{ 132 char *page; 133 int fd; 134 135 fd = scribble_object(); 136 137 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 138 0); |
139 if (page == MAP_FAILED) 140 atf_tc_fail("mmap(2) failed; errno=%d", errno); |
141 |
142 if (page[0] != '1') 143 atf_tc_fail("missing data ('%c' != '1')", page[0]); |
144 145 close(fd); |
146 if (munmap(page, getpagesize()) < 0) 147 atf_tc_fail("munmap failed; errno=%d", errno); |
148 |
149 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 150 "shm_unlink failed; errno=%d", errno); |
151} 152 153ATF_TC_WITHOUT_HEAD(reopen_object); 154ATF_TC_BODY(reopen_object, tc) 155{ 156 char *page; 157 int fd; 158 159 fd = scribble_object(); 160 close(fd); 161 162 fd = shm_open(test_path, O_RDONLY, 0777); |
163 if (fd < 0) 164 atf_tc_fail("shm_open(2) failed; errno=%d", errno); 165 |
166 page = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); |
167 if (page == MAP_FAILED) 168 atf_tc_fail("mmap(2) failed; errno=%d", errno); |
169 |
170 if (page[0] != '1') 171 atf_tc_fail("missing data ('%c' != '1')", page[0]); |
172 173 munmap(page, getpagesize()); 174 close(fd); |
175 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 176 "shm_unlink failed; errno=%d", errno); |
177} 178 179ATF_TC_WITHOUT_HEAD(readonly_mmap_write); 180ATF_TC_BODY(readonly_mmap_write, tc) 181{ 182 char *page; 183 int fd; 184 185 gen_test_path(); 186 187 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); |
188 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); |
189 190 /* PROT_WRITE should fail with EACCES. */ 191 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 192 0); |
193 if (page != MAP_FAILED) 194 atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly"); |
195 |
196 if (errno != EACCES) 197 atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; " 198 "errno=%d", errno); 199 |
200 close(fd); |
201 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 202 "shm_unlink failed; errno=%d", errno); |
203} 204 205ATF_TC_WITHOUT_HEAD(open_after_link); 206ATF_TC_BODY(open_after_link, tc) 207{ 208 int fd; 209 210 gen_test_path(); 211 212 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); |
213 ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); |
214 close(fd); 215 |
216 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d", 217 errno); |
218 219 shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT); 220} 221 222ATF_TC_WITHOUT_HEAD(open_invalid_path); 223ATF_TC_BODY(open_invalid_path, tc) 224{ 225 --- 19 unchanged lines hidden (view full) --- 245} 246 247ATF_TC_WITHOUT_HEAD(open_anon); 248ATF_TC_BODY(open_anon, tc) 249{ 250 int fd; 251 252 fd = shm_open(SHM_ANON, O_RDWR, 0777); |
253 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); |
254 close(fd); 255} 256 257ATF_TC_WITHOUT_HEAD(open_anon_readonly); 258ATF_TC_BODY(open_anon_readonly, tc) 259{ 260 261 shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); --- 28 unchanged lines hidden (view full) --- 290ATF_TC_WITHOUT_HEAD(open_create_existing_object); 291ATF_TC_BODY(open_create_existing_object, tc) 292{ 293 int fd; 294 295 gen_test_path(); 296 297 fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777); |
298 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); |
299 close(fd); 300 301 shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL, 302 0777, EEXIST); 303 |
304 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 305 "shm_unlink failed; errno=%d", errno); |
306} 307 308ATF_TC_WITHOUT_HEAD(trunc_resets_object); 309ATF_TC_BODY(trunc_resets_object, tc) 310{ 311 struct stat sb; 312 int fd; 313 314 gen_test_path(); 315 316 /* Create object and set size to 1024. */ 317 fd = shm_open(test_path, O_RDWR | O_CREAT, 0777); |
318 ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 319 ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1, 320 "ftruncate failed; errno=%d", errno); 321 ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 322 "fstat(1) failed; errno=%d", errno); 323 ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size); |
324 close(fd); 325 326 /* Open with O_TRUNC which should reset size to 0. */ 327 fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777); |
328 ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno); 329 ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 330 "fstat(2) failed; errno=%d", errno); 331 ATF_REQUIRE_MSG(sb.st_size == 0, 332 "size was not 0 after truncation: %d", (int)sb.st_size); |
333 close(fd); |
334 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 335 "shm_unlink failed; errno=%d", errno); |
336} 337 338ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer); 339ATF_TC_BODY(unlink_bad_path_pointer, tc) 340{ 341 342 shm_unlink_should_fail((char *)1024, EFAULT); 343} --- 10 unchanged lines hidden (view full) --- 354 free(page); 355} 356 357ATF_TC_WITHOUT_HEAD(object_resize); 358ATF_TC_BODY(object_resize, tc) 359{ 360 pid_t pid; 361 struct stat sb; |
362 char err_buf[1024], *page; |
363 int fd, status; 364 365 /* Start off with a size of a single page. */ |
366 fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777); 367 if (fd < 0) 368 atf_tc_fail("shm_open failed; errno=%d", errno); |
369 |
370 if (ftruncate(fd, getpagesize()) < 0) 371 atf_tc_fail("ftruncate(1) failed; errno=%d", errno); 372 373 if (fstat(fd, &sb) < 0) 374 atf_tc_fail("fstat(1) failed; errno=%d", errno); 375 376 if (sb.st_size != getpagesize()) 377 atf_tc_fail("first resize failed (%d != %d)", 378 (int)sb.st_size, getpagesize()); 379 |
380 /* Write a '1' to the first byte. */ |
381 page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, |
382 0); |
383 if (page == MAP_FAILED) |
384 atf_tc_fail("mmap(1)"); |
385 386 page[0] = '1'; 387 |
388 if (munmap(page, getpagesize()) < 0) 389 atf_tc_fail("munmap(1) failed; errno=%d", errno); |
390 391 /* Grow the object to 2 pages. */ |
392 if (ftruncate(fd, getpagesize() * 2) < 0) 393 atf_tc_fail("ftruncate(2) failed; errno=%d", errno); |
394 |
395 if (fstat(fd, &sb) < 0) 396 atf_tc_fail("fstat(2) failed; errno=%d", errno); 397 398 if (sb.st_size != getpagesize() * 2) 399 atf_tc_fail("second resize failed (%d != %d)", 400 (int)sb.st_size, getpagesize() * 2); 401 |
402 /* Check for '1' at the first byte. */ |
403 page = mmap(0, getpagesize() * 2, PROT_READ|PROT_WRITE, MAP_SHARED, |
404 fd, 0); |
405 if (page == MAP_FAILED) 406 atf_tc_fail("mmap(2) failed; errno=%d", errno); |
407 |
408 if (page[0] != '1') 409 atf_tc_fail("'%c' != '1'", page[0]); |
410 411 /* Write a '2' at the start of the second page. */ 412 page[getpagesize()] = '2'; 413 414 /* Shrink the object back to 1 page. */ |
415 if (ftruncate(fd, getpagesize()) < 0) 416 atf_tc_fail("ftruncate(3) failed; errno=%d", errno); |
417 |
418 if (fstat(fd, &sb) < 0) 419 atf_tc_fail("fstat(3) failed; errno=%d", errno); 420 421 if (sb.st_size != getpagesize()) 422 atf_tc_fail("third resize failed (%d != %d)", 423 (int)sb.st_size, getpagesize()); 424 |
425 /* 426 * Fork a child process to make sure the second page is no 427 * longer valid. 428 */ 429 pid = fork(); |
430 if (pid == -1) 431 atf_tc_fail("fork failed; errno=%d", errno); |
432 433 if (pid == 0) { 434 struct rlimit lim; 435 char c; 436 437 /* Don't generate a core dump. */ 438 getrlimit(RLIMIT_CORE, &lim); 439 lim.rlim_cur = 0; 440 setrlimit(RLIMIT_CORE, &lim); 441 442 /* 443 * The previous ftruncate(2) shrunk the backing object 444 * so that this address is no longer valid, so reading 445 * from it should trigger a SIGSEGV. 446 */ 447 c = page[getpagesize()]; 448 fprintf(stderr, "child: page 1: '%c'\n", c); 449 exit(0); 450 } |
451 452 if (wait(&status) < 0) 453 atf_tc_fail("wait failed; errno=%d", errno); 454 455 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) |
456 atf_tc_fail("child terminated with status %x", status); |
457 458 /* Grow the object back to 2 pages. */ |
459 if (ftruncate(fd, getpagesize() * 2) < 0) 460 atf_tc_fail("ftruncate(2) failed; errno=%d", errno); |
461 |
462 if (fstat(fd, &sb) < 0) 463 atf_tc_fail("fstat(2) failed; errno=%d", errno); 464 465 if (sb.st_size != getpagesize() * 2) 466 atf_tc_fail("fourth resize failed (%d != %d)", 467 (int)sb.st_size, getpagesize()); 468 |
469 /* 470 * Note that the mapping at 'page' for the second page is 471 * still valid, and now that the shm object has been grown 472 * back up to 2 pages, there is now memory backing this page 473 * so the read will work. However, the data should be zero 474 * rather than '2' as the old data was thrown away when the 475 * object was shrunk and the new pages when an object are 476 * grown are zero-filled. 477 */ |
478 if (page[getpagesize()] != 0) 479 atf_tc_fail("invalid data at %d: %x != 0", 480 getpagesize(), (int)page[getpagesize()]); |
481 482 close(fd); 483} 484 485/* Signal handler which does nothing. */ 486static void 487ignoreit(int sig __unused) 488{ --- 141 unchanged lines hidden --- |