1175383Sjhb/*- 2175383Sjhb * Copyright (c) 2006 Robert N. M. Watson 3175383Sjhb * All rights reserved. 4175383Sjhb * 5175383Sjhb * Redistribution and use in source and binary forms, with or without 6175383Sjhb * modification, are permitted provided that the following conditions 7175383Sjhb * are met: 8175383Sjhb * 1. Redistributions of source code must retain the above copyright 9175383Sjhb * notice, this list of conditions and the following disclaimer. 10175383Sjhb * 2. Redistributions in binary form must reproduce the above copyright 11175383Sjhb * notice, this list of conditions and the following disclaimer in the 12175383Sjhb * documentation and/or other materials provided with the distribution. 13175383Sjhb * 14175383Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15175383Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16175383Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17175383Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18175383Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19175383Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20175383Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21175383Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22175383Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23175383Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24175383Sjhb * SUCH DAMAGE. 25175383Sjhb */ 26175383Sjhb 27175383Sjhb#include <sys/cdefs.h> 28175383Sjhb__FBSDID("$FreeBSD: releng/11.0/tests/sys/posixshm/posixshm_test.c 298304 2016-04-19 23:15:47Z ngie $"); 29175383Sjhb 30175383Sjhb#include <sys/param.h> 31175383Sjhb#include <sys/mman.h> 32175383Sjhb#include <sys/resource.h> 33175383Sjhb#include <sys/stat.h> 34175383Sjhb#include <sys/syscall.h> 35175383Sjhb#include <sys/wait.h> 36175383Sjhb 37175383Sjhb#include <errno.h> 38175383Sjhb#include <fcntl.h> 39289437Sngie#include <signal.h> 40175383Sjhb#include <stdio.h> 41175383Sjhb#include <stdlib.h> 42175383Sjhb#include <string.h> 43175383Sjhb#include <unistd.h> 44175383Sjhb 45289437Sngie#include <atf-c.h> 46175383Sjhb 47289437Sngie#define TEST_PATH_LEN 256 48289437Sngiestatic char test_path[TEST_PATH_LEN]; 49175383Sjhb 50289437Sngiestatic void 51289437Sngiegen_test_path(void) 52289437Sngie{ 53289437Sngie 54298304Sngie snprintf(test_path, sizeof(test_path), "%s/tmp.XXXXXX", 55298304Sngie getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR")); 56289437Sngie test_path[sizeof(test_path) - 1] = '\0'; 57289437Sngie ATF_REQUIRE_MSG(mkstemp(test_path) != -1, 58289437Sngie "mkstemp failed; errno=%d", errno); 59289437Sngie ATF_REQUIRE_MSG(unlink(test_path) == 0, 60289437Sngie "unlink failed; errno=%d", errno); 61289437Sngie} 62289437Sngie 63175383Sjhb/* 64175383Sjhb * Attempt a shm_open() that should fail with an expected error of 'error'. 65175383Sjhb */ 66175383Sjhbstatic void 67175383Sjhbshm_open_should_fail(const char *path, int flags, mode_t mode, int error) 68175383Sjhb{ 69175383Sjhb int fd; 70175383Sjhb 71175383Sjhb fd = shm_open(path, flags, mode); 72289437Sngie ATF_CHECK_MSG(fd == -1, "shm_open didn't fail"); 73289437Sngie ATF_CHECK_MSG(error == errno, 74289437Sngie "shm_open didn't fail with expected errno; errno=%d; expected " 75289437Sngie "errno=%d", errno, error); 76175383Sjhb} 77175383Sjhb 78175383Sjhb/* 79175383Sjhb * Attempt a shm_unlink() that should fail with an expected error of 'error'. 80175383Sjhb */ 81175383Sjhbstatic void 82175383Sjhbshm_unlink_should_fail(const char *path, int error) 83175383Sjhb{ 84175383Sjhb 85289437Sngie ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail"); 86289437Sngie ATF_CHECK_MSG(error == errno, 87289437Sngie "shm_unlink didn't fail with expected errno; errno=%d; expected " 88289437Sngie "errno=%d", errno, error); 89175383Sjhb} 90175383Sjhb 91175383Sjhb/* 92175383Sjhb * Open the test object and write '1' to the first byte. Returns valid fd 93175383Sjhb * on success and -1 on failure. 94175383Sjhb */ 95175383Sjhbstatic int 96175383Sjhbscribble_object(void) 97175383Sjhb{ 98175383Sjhb char *page; 99298304Sngie int fd, pagesize; 100175383Sjhb 101289437Sngie gen_test_path(); 102289437Sngie 103298304Sngie ATF_REQUIRE(0 < (pagesize = getpagesize())); 104298304Sngie 105289437Sngie fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777); 106175383Sjhb if (fd < 0 && errno == EEXIST) { 107289437Sngie if (shm_unlink(test_path) < 0) 108289437Sngie atf_tc_fail("shm_unlink"); 109289437Sngie fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 110175383Sjhb } 111289437Sngie if (fd < 0) 112289441Sngie atf_tc_fail("shm_open failed; errno=%d", errno); 113298304Sngie if (ftruncate(fd, pagesize) < 0) 114289441Sngie atf_tc_fail("ftruncate failed; errno=%d", errno); 115175383Sjhb 116298304Sngie page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 117289437Sngie if (page == MAP_FAILED) 118289441Sngie atf_tc_fail("mmap failed; errno=%d", errno); 119175383Sjhb 120175383Sjhb page[0] = '1'; 121298304Sngie ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 122298304Sngie errno); 123175383Sjhb 124175383Sjhb return (fd); 125175383Sjhb} 126175383Sjhb 127289437SngieATF_TC_WITHOUT_HEAD(remap_object); 128289437SngieATF_TC_BODY(remap_object, tc) 129175383Sjhb{ 130175383Sjhb char *page; 131298304Sngie int fd, pagesize; 132175383Sjhb 133298304Sngie ATF_REQUIRE(0 < (pagesize = getpagesize())); 134298304Sngie 135175383Sjhb fd = scribble_object(); 136175383Sjhb 137298304Sngie page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 138289441Sngie if (page == MAP_FAILED) 139289441Sngie atf_tc_fail("mmap(2) failed; errno=%d", errno); 140175383Sjhb 141289441Sngie if (page[0] != '1') 142289441Sngie atf_tc_fail("missing data ('%c' != '1')", page[0]); 143175383Sjhb 144175383Sjhb close(fd); 145298304Sngie ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 146298304Sngie errno); 147175383Sjhb 148289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 149289441Sngie "shm_unlink failed; errno=%d", errno); 150175383Sjhb} 151175383Sjhb 152289437SngieATF_TC_WITHOUT_HEAD(reopen_object); 153289437SngieATF_TC_BODY(reopen_object, tc) 154175383Sjhb{ 155175383Sjhb char *page; 156298304Sngie int fd, pagesize; 157175383Sjhb 158298304Sngie ATF_REQUIRE(0 < (pagesize = getpagesize())); 159298304Sngie 160175383Sjhb fd = scribble_object(); 161175383Sjhb close(fd); 162175383Sjhb 163289437Sngie fd = shm_open(test_path, O_RDONLY, 0777); 164289441Sngie if (fd < 0) 165289441Sngie atf_tc_fail("shm_open(2) failed; errno=%d", errno); 166289441Sngie 167298304Sngie page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 168289441Sngie if (page == MAP_FAILED) 169289441Sngie atf_tc_fail("mmap(2) failed; errno=%d", errno); 170175383Sjhb 171289441Sngie if (page[0] != '1') 172289441Sngie atf_tc_fail("missing data ('%c' != '1')", page[0]); 173175383Sjhb 174298304Sngie ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 175298304Sngie errno); 176175383Sjhb close(fd); 177289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 178289441Sngie "shm_unlink failed; errno=%d", errno); 179175383Sjhb} 180175383Sjhb 181289437SngieATF_TC_WITHOUT_HEAD(readonly_mmap_write); 182289437SngieATF_TC_BODY(readonly_mmap_write, tc) 183175383Sjhb{ 184175383Sjhb char *page; 185298304Sngie int fd, pagesize; 186175383Sjhb 187298304Sngie ATF_REQUIRE(0 < (pagesize = getpagesize())); 188298304Sngie 189289437Sngie gen_test_path(); 190289437Sngie 191289437Sngie fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 192289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 193175383Sjhb 194175383Sjhb /* PROT_WRITE should fail with EACCES. */ 195298304Sngie page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 196289441Sngie if (page != MAP_FAILED) 197289441Sngie atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly"); 198175383Sjhb 199289441Sngie if (errno != EACCES) 200289441Sngie atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; " 201289441Sngie "errno=%d", errno); 202289441Sngie 203175383Sjhb close(fd); 204289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 205289441Sngie "shm_unlink failed; errno=%d", errno); 206175383Sjhb} 207175383Sjhb 208289437SngieATF_TC_WITHOUT_HEAD(open_after_link); 209289437SngieATF_TC_BODY(open_after_link, tc) 210175383Sjhb{ 211175383Sjhb int fd; 212175383Sjhb 213289437Sngie gen_test_path(); 214289437Sngie 215289437Sngie fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 216289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 217175383Sjhb close(fd); 218175383Sjhb 219289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d", 220289441Sngie errno); 221175383Sjhb 222289437Sngie shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT); 223175383Sjhb} 224175383Sjhb 225289437SngieATF_TC_WITHOUT_HEAD(open_invalid_path); 226289437SngieATF_TC_BODY(open_invalid_path, tc) 227175383Sjhb{ 228175383Sjhb 229175383Sjhb shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL); 230175383Sjhb} 231175383Sjhb 232289437SngieATF_TC_WITHOUT_HEAD(open_write_only); 233289437SngieATF_TC_BODY(open_write_only, tc) 234175383Sjhb{ 235175383Sjhb 236289437Sngie gen_test_path(); 237289437Sngie 238289437Sngie shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL); 239175383Sjhb} 240175383Sjhb 241289437SngieATF_TC_WITHOUT_HEAD(open_extra_flags); 242289437SngieATF_TC_BODY(open_extra_flags, tc) 243175383Sjhb{ 244175383Sjhb 245289437Sngie gen_test_path(); 246289437Sngie 247289437Sngie shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL); 248175383Sjhb} 249175383Sjhb 250289437SngieATF_TC_WITHOUT_HEAD(open_anon); 251289437SngieATF_TC_BODY(open_anon, tc) 252175383Sjhb{ 253175383Sjhb int fd; 254175383Sjhb 255175383Sjhb fd = shm_open(SHM_ANON, O_RDWR, 0777); 256289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 257175383Sjhb close(fd); 258175383Sjhb} 259175383Sjhb 260289437SngieATF_TC_WITHOUT_HEAD(open_anon_readonly); 261289437SngieATF_TC_BODY(open_anon_readonly, tc) 262175383Sjhb{ 263175383Sjhb 264175383Sjhb shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); 265175383Sjhb} 266175383Sjhb 267289437SngieATF_TC_WITHOUT_HEAD(open_bad_path_pointer); 268289437SngieATF_TC_BODY(open_bad_path_pointer, tc) 269175383Sjhb{ 270175383Sjhb 271175383Sjhb shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT); 272175383Sjhb} 273175383Sjhb 274289437SngieATF_TC_WITHOUT_HEAD(open_path_too_long); 275289437SngieATF_TC_BODY(open_path_too_long, tc) 276175383Sjhb{ 277175383Sjhb char *page; 278175383Sjhb 279175383Sjhb page = malloc(MAXPATHLEN + 1); 280175383Sjhb memset(page, 'a', MAXPATHLEN); 281175383Sjhb page[MAXPATHLEN] = '\0'; 282175383Sjhb shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG); 283175383Sjhb free(page); 284175383Sjhb} 285175383Sjhb 286289437SngieATF_TC_WITHOUT_HEAD(open_nonexisting_object); 287289437SngieATF_TC_BODY(open_nonexisting_object, tc) 288175383Sjhb{ 289175383Sjhb 290175383Sjhb shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT); 291175383Sjhb} 292175383Sjhb 293289437SngieATF_TC_WITHOUT_HEAD(open_create_existing_object); 294289437SngieATF_TC_BODY(open_create_existing_object, tc) 295175383Sjhb{ 296175383Sjhb int fd; 297175383Sjhb 298289437Sngie gen_test_path(); 299289437Sngie 300289437Sngie fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777); 301289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 302175383Sjhb close(fd); 303175383Sjhb 304289437Sngie shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL, 305175383Sjhb 0777, EEXIST); 306175383Sjhb 307289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 308289441Sngie "shm_unlink failed; errno=%d", errno); 309175383Sjhb} 310175383Sjhb 311289437SngieATF_TC_WITHOUT_HEAD(trunc_resets_object); 312289437SngieATF_TC_BODY(trunc_resets_object, tc) 313175383Sjhb{ 314175383Sjhb struct stat sb; 315175383Sjhb int fd; 316175383Sjhb 317289437Sngie gen_test_path(); 318289437Sngie 319175383Sjhb /* Create object and set size to 1024. */ 320289437Sngie fd = shm_open(test_path, O_RDWR | O_CREAT, 0777); 321289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 322289441Sngie ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1, 323289441Sngie "ftruncate failed; errno=%d", errno); 324289441Sngie ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 325289441Sngie "fstat(1) failed; errno=%d", errno); 326289441Sngie ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size); 327175383Sjhb close(fd); 328175383Sjhb 329175383Sjhb /* Open with O_TRUNC which should reset size to 0. */ 330289437Sngie fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777); 331289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno); 332289441Sngie ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 333289441Sngie "fstat(2) failed; errno=%d", errno); 334289441Sngie ATF_REQUIRE_MSG(sb.st_size == 0, 335289441Sngie "size was not 0 after truncation: %d", (int)sb.st_size); 336175383Sjhb close(fd); 337289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 338289441Sngie "shm_unlink failed; errno=%d", errno); 339175383Sjhb} 340175383Sjhb 341289437SngieATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer); 342289437SngieATF_TC_BODY(unlink_bad_path_pointer, tc) 343175383Sjhb{ 344175383Sjhb 345175383Sjhb shm_unlink_should_fail((char *)1024, EFAULT); 346175383Sjhb} 347175383Sjhb 348289437SngieATF_TC_WITHOUT_HEAD(unlink_path_too_long); 349289437SngieATF_TC_BODY(unlink_path_too_long, tc) 350175383Sjhb{ 351175383Sjhb char *page; 352175383Sjhb 353175383Sjhb page = malloc(MAXPATHLEN + 1); 354175383Sjhb memset(page, 'a', MAXPATHLEN); 355175383Sjhb page[MAXPATHLEN] = '\0'; 356175383Sjhb shm_unlink_should_fail(page, ENAMETOOLONG); 357175383Sjhb free(page); 358175383Sjhb} 359175383Sjhb 360289437SngieATF_TC_WITHOUT_HEAD(object_resize); 361289437SngieATF_TC_BODY(object_resize, tc) 362175383Sjhb{ 363175383Sjhb pid_t pid; 364175383Sjhb struct stat sb; 365298304Sngie char *page; 366298304Sngie int fd, pagesize, status; 367175383Sjhb 368298304Sngie ATF_REQUIRE(0 < (pagesize = getpagesize())); 369298304Sngie 370175383Sjhb /* Start off with a size of a single page. */ 371289441Sngie fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777); 372289441Sngie if (fd < 0) 373289441Sngie atf_tc_fail("shm_open failed; errno=%d", errno); 374175383Sjhb 375298304Sngie if (ftruncate(fd, pagesize) < 0) 376289441Sngie atf_tc_fail("ftruncate(1) failed; errno=%d", errno); 377289441Sngie 378289441Sngie if (fstat(fd, &sb) < 0) 379289441Sngie atf_tc_fail("fstat(1) failed; errno=%d", errno); 380289441Sngie 381298304Sngie if (sb.st_size != pagesize) 382289441Sngie atf_tc_fail("first resize failed (%d != %d)", 383298304Sngie (int)sb.st_size, pagesize); 384289441Sngie 385175383Sjhb /* Write a '1' to the first byte. */ 386298304Sngie page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 387289441Sngie if (page == MAP_FAILED) 388289437Sngie atf_tc_fail("mmap(1)"); 389175383Sjhb 390175383Sjhb page[0] = '1'; 391175383Sjhb 392298304Sngie ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 393298304Sngie errno); 394175383Sjhb 395175383Sjhb /* Grow the object to 2 pages. */ 396298304Sngie if (ftruncate(fd, pagesize * 2) < 0) 397289441Sngie atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 398175383Sjhb 399289441Sngie if (fstat(fd, &sb) < 0) 400289441Sngie atf_tc_fail("fstat(2) failed; errno=%d", errno); 401289441Sngie 402298304Sngie if (sb.st_size != pagesize * 2) 403289441Sngie atf_tc_fail("second resize failed (%d != %d)", 404298304Sngie (int)sb.st_size, pagesize * 2); 405289441Sngie 406175383Sjhb /* Check for '1' at the first byte. */ 407298304Sngie page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 408289441Sngie if (page == MAP_FAILED) 409289441Sngie atf_tc_fail("mmap(2) failed; errno=%d", errno); 410175383Sjhb 411289441Sngie if (page[0] != '1') 412289441Sngie atf_tc_fail("'%c' != '1'", page[0]); 413175383Sjhb 414175383Sjhb /* Write a '2' at the start of the second page. */ 415298304Sngie page[pagesize] = '2'; 416175383Sjhb 417175383Sjhb /* Shrink the object back to 1 page. */ 418298304Sngie if (ftruncate(fd, pagesize) < 0) 419289441Sngie atf_tc_fail("ftruncate(3) failed; errno=%d", errno); 420175383Sjhb 421289441Sngie if (fstat(fd, &sb) < 0) 422289441Sngie atf_tc_fail("fstat(3) failed; errno=%d", errno); 423289441Sngie 424298304Sngie if (sb.st_size != pagesize) 425289441Sngie atf_tc_fail("third resize failed (%d != %d)", 426298304Sngie (int)sb.st_size, pagesize); 427289441Sngie 428175383Sjhb /* 429175383Sjhb * Fork a child process to make sure the second page is no 430175383Sjhb * longer valid. 431175383Sjhb */ 432175383Sjhb pid = fork(); 433289441Sngie if (pid == -1) 434289441Sngie atf_tc_fail("fork failed; errno=%d", errno); 435175383Sjhb 436175383Sjhb if (pid == 0) { 437175383Sjhb struct rlimit lim; 438175383Sjhb char c; 439175383Sjhb 440175383Sjhb /* Don't generate a core dump. */ 441298304Sngie ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0); 442175383Sjhb lim.rlim_cur = 0; 443298304Sngie ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0); 444175383Sjhb 445175383Sjhb /* 446175383Sjhb * The previous ftruncate(2) shrunk the backing object 447175383Sjhb * so that this address is no longer valid, so reading 448175383Sjhb * from it should trigger a SIGSEGV. 449175383Sjhb */ 450298304Sngie c = page[pagesize]; 451175383Sjhb fprintf(stderr, "child: page 1: '%c'\n", c); 452175383Sjhb exit(0); 453175383Sjhb } 454289441Sngie 455289441Sngie if (wait(&status) < 0) 456289441Sngie atf_tc_fail("wait failed; errno=%d", errno); 457289441Sngie 458289441Sngie if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) 459289437Sngie atf_tc_fail("child terminated with status %x", status); 460175383Sjhb 461175383Sjhb /* Grow the object back to 2 pages. */ 462298304Sngie if (ftruncate(fd, pagesize * 2) < 0) 463289441Sngie atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 464175383Sjhb 465289441Sngie if (fstat(fd, &sb) < 0) 466289441Sngie atf_tc_fail("fstat(2) failed; errno=%d", errno); 467289441Sngie 468298304Sngie if (sb.st_size != pagesize * 2) 469289441Sngie atf_tc_fail("fourth resize failed (%d != %d)", 470298304Sngie (int)sb.st_size, pagesize); 471289441Sngie 472175383Sjhb /* 473175383Sjhb * Note that the mapping at 'page' for the second page is 474175383Sjhb * still valid, and now that the shm object has been grown 475175383Sjhb * back up to 2 pages, there is now memory backing this page 476175383Sjhb * so the read will work. However, the data should be zero 477175383Sjhb * rather than '2' as the old data was thrown away when the 478175383Sjhb * object was shrunk and the new pages when an object are 479175383Sjhb * grown are zero-filled. 480175383Sjhb */ 481298304Sngie if (page[pagesize] != 0) 482289441Sngie atf_tc_fail("invalid data at %d: %x != 0", 483298304Sngie pagesize, (int)page[pagesize]); 484175383Sjhb 485175383Sjhb close(fd); 486175383Sjhb} 487175383Sjhb 488289437Sngie/* Signal handler which does nothing. */ 489289437Sngiestatic void 490289437Sngieignoreit(int sig __unused) 491175383Sjhb{ 492289437Sngie ; 493289437Sngie} 494175383Sjhb 495289437SngieATF_TC_WITHOUT_HEAD(shm_functionality_across_fork); 496289437SngieATF_TC_BODY(shm_functionality_across_fork, tc) 497289437Sngie{ 498289437Sngie char *cp, c; 499289437Sngie int error, desc, rv; 500289437Sngie long scval; 501289437Sngie sigset_t ss; 502289437Sngie struct sigaction sa; 503289437Sngie void *region; 504289437Sngie size_t i, psize; 505289437Sngie 506289437Sngie#ifndef _POSIX_SHARED_MEMORY_OBJECTS 507289437Sngie printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 508289437Sngie#else 509289437Sngie printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 510289437Sngie (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 511289437Sngie if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 512289437Sngie printf("***Indicates this feature may be unsupported!\n"); 513289437Sngie#endif 514289437Sngie errno = 0; 515289437Sngie scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 516289437Sngie if (scval == -1 && errno != 0) { 517289437Sngie atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; " 518289437Sngie "errno=%d", errno); 519289437Sngie } else { 520289437Sngie printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 521289437Sngie scval); 522289437Sngie if (scval == -1) 523289437Sngie printf("***Indicates this feature is unsupported!\n"); 524289437Sngie } 525289437Sngie 526289437Sngie errno = 0; 527289437Sngie scval = sysconf(_SC_PAGESIZE); 528289437Sngie if (scval == -1 && errno != 0) { 529289437Sngie atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno); 530298304Sngie } else if (scval <= 0) { 531289437Sngie fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld", 532289437Sngie scval); 533289437Sngie psize = 4096; 534289437Sngie } else { 535289437Sngie printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 536289437Sngie psize = scval; 537289437Sngie } 538289437Sngie 539289437Sngie gen_test_path(); 540289437Sngie desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600); 541289437Sngie 542289437Sngie ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno); 543289437Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 544289437Sngie "shm_unlink failed; errno=%d", errno); 545289437Sngie ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1, 546289437Sngie "ftruncate failed; errno=%d", errno); 547289437Sngie 548298304Sngie region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0); 549289437Sngie ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno); 550289437Sngie memset(region, '\377', psize); 551289437Sngie 552289437Sngie sa.sa_flags = 0; 553289437Sngie sa.sa_handler = ignoreit; 554289437Sngie sigemptyset(&sa.sa_mask); 555289437Sngie ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0, 556289437Sngie "sigaction failed; errno=%d", errno); 557289437Sngie 558289437Sngie sigemptyset(&ss); 559289437Sngie sigaddset(&ss, SIGUSR1); 560289437Sngie ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0, 561289437Sngie "sigprocmask failed; errno=%d", errno); 562289437Sngie 563289437Sngie rv = fork(); 564289437Sngie ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno); 565289437Sngie if (rv == 0) { 566289437Sngie sigemptyset(&ss); 567289437Sngie sigsuspend(&ss); 568289437Sngie 569289437Sngie for (cp = region; cp < (char *)region + psize; cp++) { 570289437Sngie if (*cp != '\151') 571289437Sngie _exit(1); 572289437Sngie } 573289437Sngie if (lseek(desc, 0, SEEK_SET) == -1) 574289437Sngie _exit(1); 575289437Sngie for (i = 0; i < psize; i++) { 576289437Sngie error = read(desc, &c, 1); 577289437Sngie if (c != '\151') 578289437Sngie _exit(1); 579289437Sngie } 580289437Sngie _exit(0); 581289437Sngie } else { 582289437Sngie int status; 583289437Sngie 584289437Sngie memset(region, '\151', psize - 2); 585289437Sngie error = pwrite(desc, region, 2, psize - 2); 586289437Sngie if (error != 2) { 587289437Sngie if (error >= 0) 588289437Sngie atf_tc_fail("short write; %d bytes written", 589289437Sngie error); 590289437Sngie else 591289437Sngie atf_tc_fail("shmfd write"); 592289437Sngie } 593289437Sngie kill(rv, SIGUSR1); 594289437Sngie waitpid(rv, &status, 0); 595289437Sngie 596289437Sngie if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 597289437Sngie printf("Functionality test successful\n"); 598289437Sngie } else if (WIFEXITED(status)) { 599289437Sngie atf_tc_fail("Child process exited with status %d", 600289437Sngie WEXITSTATUS(status)); 601289437Sngie } else { 602289437Sngie atf_tc_fail("Child process terminated with %s", 603289437Sngie strsignal(WTERMSIG(status))); 604289437Sngie } 605289437Sngie } 606298304Sngie 607298304Sngie ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d", 608298304Sngie errno); 609298304Sngie shm_unlink(test_path); 610175383Sjhb} 611289437Sngie 612289437SngieATF_TP_ADD_TCS(tp) 613289437Sngie{ 614289437Sngie 615289437Sngie ATF_TP_ADD_TC(tp, remap_object); 616289437Sngie ATF_TP_ADD_TC(tp, reopen_object); 617289437Sngie ATF_TP_ADD_TC(tp, readonly_mmap_write); 618289437Sngie ATF_TP_ADD_TC(tp, open_after_link); 619289437Sngie ATF_TP_ADD_TC(tp, open_invalid_path); 620289437Sngie ATF_TP_ADD_TC(tp, open_write_only); 621289437Sngie ATF_TP_ADD_TC(tp, open_extra_flags); 622289437Sngie ATF_TP_ADD_TC(tp, open_anon); 623289437Sngie ATF_TP_ADD_TC(tp, open_anon_readonly); 624289437Sngie ATF_TP_ADD_TC(tp, open_bad_path_pointer); 625289437Sngie ATF_TP_ADD_TC(tp, open_path_too_long); 626289437Sngie ATF_TP_ADD_TC(tp, open_nonexisting_object); 627289437Sngie ATF_TP_ADD_TC(tp, open_create_existing_object); 628289437Sngie ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 629289437Sngie ATF_TP_ADD_TC(tp, trunc_resets_object); 630289437Sngie ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 631289437Sngie ATF_TP_ADD_TC(tp, unlink_path_too_long); 632289437Sngie ATF_TP_ADD_TC(tp, object_resize); 633289437Sngie 634289437Sngie return (atf_no_error()); 635289437Sngie} 636