posixshm_test.c revision 289441
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: head/tests/sys/posixshm/posixshm_test.c 289441 2015-10-17 04:32:21Z 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 char *tmpdir = getenv("TMPDIR"); 54289437Sngie 55289437Sngie if (tmpdir == NULL) 56289437Sngie tmpdir = "/tmp"; 57289437Sngie 58289437Sngie snprintf(test_path, sizeof(test_path), "%s/tmp.XXXXXX", tmpdir); 59289437Sngie test_path[sizeof(test_path) - 1] = '\0'; 60289437Sngie ATF_REQUIRE_MSG(mkstemp(test_path) != -1, 61289437Sngie "mkstemp failed; errno=%d", errno); 62289437Sngie ATF_REQUIRE_MSG(unlink(test_path) == 0, 63289437Sngie "unlink failed; errno=%d", errno); 64289437Sngie} 65289437Sngie 66175383Sjhb/* 67175383Sjhb * Attempt a shm_open() that should fail with an expected error of 'error'. 68175383Sjhb */ 69175383Sjhbstatic void 70175383Sjhbshm_open_should_fail(const char *path, int flags, mode_t mode, int error) 71175383Sjhb{ 72175383Sjhb int fd; 73175383Sjhb 74175383Sjhb fd = shm_open(path, flags, mode); 75289437Sngie ATF_CHECK_MSG(fd == -1, "shm_open didn't fail"); 76289437Sngie ATF_CHECK_MSG(error == errno, 77289437Sngie "shm_open didn't fail with expected errno; errno=%d; expected " 78289437Sngie "errno=%d", errno, error); 79175383Sjhb} 80175383Sjhb 81175383Sjhb/* 82175383Sjhb * Attempt a shm_unlink() that should fail with an expected error of 'error'. 83175383Sjhb */ 84175383Sjhbstatic void 85175383Sjhbshm_unlink_should_fail(const char *path, int error) 86175383Sjhb{ 87175383Sjhb 88289437Sngie ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail"); 89289437Sngie ATF_CHECK_MSG(error == errno, 90289437Sngie "shm_unlink didn't fail with expected errno; errno=%d; expected " 91289437Sngie "errno=%d", errno, error); 92175383Sjhb} 93175383Sjhb 94175383Sjhb/* 95175383Sjhb * Open the test object and write '1' to the first byte. Returns valid fd 96175383Sjhb * on success and -1 on failure. 97175383Sjhb */ 98175383Sjhbstatic int 99175383Sjhbscribble_object(void) 100175383Sjhb{ 101175383Sjhb char *page; 102175383Sjhb int fd; 103175383Sjhb 104289437Sngie gen_test_path(); 105289437Sngie 106289437Sngie fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777); 107175383Sjhb if (fd < 0 && errno == EEXIST) { 108289437Sngie if (shm_unlink(test_path) < 0) 109289437Sngie atf_tc_fail("shm_unlink"); 110289437Sngie fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 111175383Sjhb } 112289437Sngie if (fd < 0) 113289441Sngie atf_tc_fail("shm_open failed; errno=%d", errno); 114289437Sngie if (ftruncate(fd, getpagesize()) < 0) 115289441Sngie atf_tc_fail("ftruncate failed; errno=%d", errno); 116175383Sjhb 117175383Sjhb page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 118175383Sjhb 0); 119289437Sngie if (page == MAP_FAILED) 120289441Sngie atf_tc_fail("mmap failed; errno=%d", errno); 121175383Sjhb 122175383Sjhb page[0] = '1'; 123289437Sngie if (munmap(page, getpagesize()) < 0) 124289441Sngie atf_tc_fail("munmap failed; errno=%d", errno); 125175383Sjhb 126175383Sjhb return (fd); 127175383Sjhb} 128175383Sjhb 129289437SngieATF_TC_WITHOUT_HEAD(remap_object); 130289437SngieATF_TC_BODY(remap_object, tc) 131175383Sjhb{ 132175383Sjhb char *page; 133175383Sjhb int fd; 134175383Sjhb 135175383Sjhb fd = scribble_object(); 136175383Sjhb 137175383Sjhb page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 138175383Sjhb 0); 139289441Sngie if (page == MAP_FAILED) 140289441Sngie atf_tc_fail("mmap(2) failed; errno=%d", errno); 141175383Sjhb 142289441Sngie if (page[0] != '1') 143289441Sngie atf_tc_fail("missing data ('%c' != '1')", page[0]); 144175383Sjhb 145175383Sjhb close(fd); 146289441Sngie if (munmap(page, getpagesize()) < 0) 147289441Sngie atf_tc_fail("munmap failed; errno=%d", errno); 148175383Sjhb 149289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 150289441Sngie "shm_unlink failed; errno=%d", errno); 151175383Sjhb} 152175383Sjhb 153289437SngieATF_TC_WITHOUT_HEAD(reopen_object); 154289437SngieATF_TC_BODY(reopen_object, tc) 155175383Sjhb{ 156175383Sjhb char *page; 157175383Sjhb int fd; 158175383Sjhb 159175383Sjhb fd = scribble_object(); 160175383Sjhb close(fd); 161175383Sjhb 162289437Sngie fd = shm_open(test_path, O_RDONLY, 0777); 163289441Sngie if (fd < 0) 164289441Sngie atf_tc_fail("shm_open(2) failed; errno=%d", errno); 165289441Sngie 166175383Sjhb page = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); 167289441Sngie if (page == MAP_FAILED) 168289441Sngie atf_tc_fail("mmap(2) failed; errno=%d", errno); 169175383Sjhb 170289441Sngie if (page[0] != '1') 171289441Sngie atf_tc_fail("missing data ('%c' != '1')", page[0]); 172175383Sjhb 173175383Sjhb munmap(page, getpagesize()); 174175383Sjhb close(fd); 175289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 176289441Sngie "shm_unlink failed; errno=%d", errno); 177175383Sjhb} 178175383Sjhb 179289437SngieATF_TC_WITHOUT_HEAD(readonly_mmap_write); 180289437SngieATF_TC_BODY(readonly_mmap_write, tc) 181175383Sjhb{ 182175383Sjhb char *page; 183175383Sjhb int fd; 184175383Sjhb 185289437Sngie gen_test_path(); 186289437Sngie 187289437Sngie fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 188289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 189175383Sjhb 190175383Sjhb /* PROT_WRITE should fail with EACCES. */ 191175383Sjhb page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 192175383Sjhb 0); 193289441Sngie if (page != MAP_FAILED) 194289441Sngie atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly"); 195175383Sjhb 196289441Sngie if (errno != EACCES) 197289441Sngie atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; " 198289441Sngie "errno=%d", errno); 199289441Sngie 200175383Sjhb close(fd); 201289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 202289441Sngie "shm_unlink failed; errno=%d", errno); 203175383Sjhb} 204175383Sjhb 205289437SngieATF_TC_WITHOUT_HEAD(open_after_link); 206289437SngieATF_TC_BODY(open_after_link, tc) 207175383Sjhb{ 208175383Sjhb int fd; 209175383Sjhb 210289437Sngie gen_test_path(); 211289437Sngie 212289437Sngie fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 213289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 214175383Sjhb close(fd); 215175383Sjhb 216289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d", 217289441Sngie errno); 218175383Sjhb 219289437Sngie shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT); 220175383Sjhb} 221175383Sjhb 222289437SngieATF_TC_WITHOUT_HEAD(open_invalid_path); 223289437SngieATF_TC_BODY(open_invalid_path, tc) 224175383Sjhb{ 225175383Sjhb 226175383Sjhb shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL); 227175383Sjhb} 228175383Sjhb 229289437SngieATF_TC_WITHOUT_HEAD(open_write_only); 230289437SngieATF_TC_BODY(open_write_only, tc) 231175383Sjhb{ 232175383Sjhb 233289437Sngie gen_test_path(); 234289437Sngie 235289437Sngie shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL); 236175383Sjhb} 237175383Sjhb 238289437SngieATF_TC_WITHOUT_HEAD(open_extra_flags); 239289437SngieATF_TC_BODY(open_extra_flags, tc) 240175383Sjhb{ 241175383Sjhb 242289437Sngie gen_test_path(); 243289437Sngie 244289437Sngie shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL); 245175383Sjhb} 246175383Sjhb 247289437SngieATF_TC_WITHOUT_HEAD(open_anon); 248289437SngieATF_TC_BODY(open_anon, tc) 249175383Sjhb{ 250175383Sjhb int fd; 251175383Sjhb 252175383Sjhb fd = shm_open(SHM_ANON, O_RDWR, 0777); 253289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 254175383Sjhb close(fd); 255175383Sjhb} 256175383Sjhb 257289437SngieATF_TC_WITHOUT_HEAD(open_anon_readonly); 258289437SngieATF_TC_BODY(open_anon_readonly, tc) 259175383Sjhb{ 260175383Sjhb 261175383Sjhb shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); 262175383Sjhb} 263175383Sjhb 264289437SngieATF_TC_WITHOUT_HEAD(open_bad_path_pointer); 265289437SngieATF_TC_BODY(open_bad_path_pointer, tc) 266175383Sjhb{ 267175383Sjhb 268175383Sjhb shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT); 269175383Sjhb} 270175383Sjhb 271289437SngieATF_TC_WITHOUT_HEAD(open_path_too_long); 272289437SngieATF_TC_BODY(open_path_too_long, tc) 273175383Sjhb{ 274175383Sjhb char *page; 275175383Sjhb 276175383Sjhb page = malloc(MAXPATHLEN + 1); 277175383Sjhb memset(page, 'a', MAXPATHLEN); 278175383Sjhb page[MAXPATHLEN] = '\0'; 279175383Sjhb shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG); 280175383Sjhb free(page); 281175383Sjhb} 282175383Sjhb 283289437SngieATF_TC_WITHOUT_HEAD(open_nonexisting_object); 284289437SngieATF_TC_BODY(open_nonexisting_object, tc) 285175383Sjhb{ 286175383Sjhb 287175383Sjhb shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT); 288175383Sjhb} 289175383Sjhb 290289437SngieATF_TC_WITHOUT_HEAD(open_create_existing_object); 291289437SngieATF_TC_BODY(open_create_existing_object, tc) 292175383Sjhb{ 293175383Sjhb int fd; 294175383Sjhb 295289437Sngie gen_test_path(); 296289437Sngie 297289437Sngie fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777); 298289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 299175383Sjhb close(fd); 300175383Sjhb 301289437Sngie shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL, 302175383Sjhb 0777, EEXIST); 303175383Sjhb 304289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 305289441Sngie "shm_unlink failed; errno=%d", errno); 306175383Sjhb} 307175383Sjhb 308289437SngieATF_TC_WITHOUT_HEAD(trunc_resets_object); 309289437SngieATF_TC_BODY(trunc_resets_object, tc) 310175383Sjhb{ 311175383Sjhb struct stat sb; 312175383Sjhb int fd; 313175383Sjhb 314289437Sngie gen_test_path(); 315289437Sngie 316175383Sjhb /* Create object and set size to 1024. */ 317289437Sngie fd = shm_open(test_path, O_RDWR | O_CREAT, 0777); 318289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 319289441Sngie ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1, 320289441Sngie "ftruncate failed; errno=%d", errno); 321289441Sngie ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 322289441Sngie "fstat(1) failed; errno=%d", errno); 323289441Sngie ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size); 324175383Sjhb close(fd); 325175383Sjhb 326175383Sjhb /* Open with O_TRUNC which should reset size to 0. */ 327289437Sngie fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777); 328289441Sngie ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno); 329289441Sngie ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 330289441Sngie "fstat(2) failed; errno=%d", errno); 331289441Sngie ATF_REQUIRE_MSG(sb.st_size == 0, 332289441Sngie "size was not 0 after truncation: %d", (int)sb.st_size); 333175383Sjhb close(fd); 334289441Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 335289441Sngie "shm_unlink failed; errno=%d", errno); 336175383Sjhb} 337175383Sjhb 338289437SngieATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer); 339289437SngieATF_TC_BODY(unlink_bad_path_pointer, tc) 340175383Sjhb{ 341175383Sjhb 342175383Sjhb shm_unlink_should_fail((char *)1024, EFAULT); 343175383Sjhb} 344175383Sjhb 345289437SngieATF_TC_WITHOUT_HEAD(unlink_path_too_long); 346289437SngieATF_TC_BODY(unlink_path_too_long, tc) 347175383Sjhb{ 348175383Sjhb char *page; 349175383Sjhb 350175383Sjhb page = malloc(MAXPATHLEN + 1); 351175383Sjhb memset(page, 'a', MAXPATHLEN); 352175383Sjhb page[MAXPATHLEN] = '\0'; 353175383Sjhb shm_unlink_should_fail(page, ENAMETOOLONG); 354175383Sjhb free(page); 355175383Sjhb} 356175383Sjhb 357289437SngieATF_TC_WITHOUT_HEAD(object_resize); 358289437SngieATF_TC_BODY(object_resize, tc) 359175383Sjhb{ 360175383Sjhb pid_t pid; 361175383Sjhb struct stat sb; 362289441Sngie char err_buf[1024], *page; 363175383Sjhb int fd, status; 364175383Sjhb 365175383Sjhb /* Start off with a size of a single page. */ 366289441Sngie fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777); 367289441Sngie if (fd < 0) 368289441Sngie atf_tc_fail("shm_open failed; errno=%d", errno); 369175383Sjhb 370289441Sngie if (ftruncate(fd, getpagesize()) < 0) 371289441Sngie atf_tc_fail("ftruncate(1) failed; errno=%d", errno); 372289441Sngie 373289441Sngie if (fstat(fd, &sb) < 0) 374289441Sngie atf_tc_fail("fstat(1) failed; errno=%d", errno); 375289441Sngie 376289441Sngie if (sb.st_size != getpagesize()) 377289441Sngie atf_tc_fail("first resize failed (%d != %d)", 378289441Sngie (int)sb.st_size, getpagesize()); 379289441Sngie 380175383Sjhb /* Write a '1' to the first byte. */ 381289441Sngie page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 382175383Sjhb 0); 383289441Sngie if (page == MAP_FAILED) 384289437Sngie atf_tc_fail("mmap(1)"); 385175383Sjhb 386175383Sjhb page[0] = '1'; 387175383Sjhb 388289441Sngie if (munmap(page, getpagesize()) < 0) 389289441Sngie atf_tc_fail("munmap(1) failed; errno=%d", errno); 390175383Sjhb 391175383Sjhb /* Grow the object to 2 pages. */ 392289441Sngie if (ftruncate(fd, getpagesize() * 2) < 0) 393289441Sngie atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 394175383Sjhb 395289441Sngie if (fstat(fd, &sb) < 0) 396289441Sngie atf_tc_fail("fstat(2) failed; errno=%d", errno); 397289441Sngie 398289441Sngie if (sb.st_size != getpagesize() * 2) 399289441Sngie atf_tc_fail("second resize failed (%d != %d)", 400289441Sngie (int)sb.st_size, getpagesize() * 2); 401289441Sngie 402175383Sjhb /* Check for '1' at the first byte. */ 403289441Sngie page = mmap(0, getpagesize() * 2, PROT_READ|PROT_WRITE, MAP_SHARED, 404175383Sjhb fd, 0); 405289441Sngie if (page == MAP_FAILED) 406289441Sngie atf_tc_fail("mmap(2) failed; errno=%d", errno); 407175383Sjhb 408289441Sngie if (page[0] != '1') 409289441Sngie atf_tc_fail("'%c' != '1'", page[0]); 410175383Sjhb 411175383Sjhb /* Write a '2' at the start of the second page. */ 412175383Sjhb page[getpagesize()] = '2'; 413175383Sjhb 414175383Sjhb /* Shrink the object back to 1 page. */ 415289441Sngie if (ftruncate(fd, getpagesize()) < 0) 416289441Sngie atf_tc_fail("ftruncate(3) failed; errno=%d", errno); 417175383Sjhb 418289441Sngie if (fstat(fd, &sb) < 0) 419289441Sngie atf_tc_fail("fstat(3) failed; errno=%d", errno); 420289441Sngie 421289441Sngie if (sb.st_size != getpagesize()) 422289441Sngie atf_tc_fail("third resize failed (%d != %d)", 423289441Sngie (int)sb.st_size, getpagesize()); 424289441Sngie 425175383Sjhb /* 426175383Sjhb * Fork a child process to make sure the second page is no 427175383Sjhb * longer valid. 428175383Sjhb */ 429175383Sjhb pid = fork(); 430289441Sngie if (pid == -1) 431289441Sngie atf_tc_fail("fork failed; errno=%d", errno); 432175383Sjhb 433175383Sjhb if (pid == 0) { 434175383Sjhb struct rlimit lim; 435175383Sjhb char c; 436175383Sjhb 437175383Sjhb /* Don't generate a core dump. */ 438175383Sjhb getrlimit(RLIMIT_CORE, &lim); 439175383Sjhb lim.rlim_cur = 0; 440175383Sjhb setrlimit(RLIMIT_CORE, &lim); 441175383Sjhb 442175383Sjhb /* 443175383Sjhb * The previous ftruncate(2) shrunk the backing object 444175383Sjhb * so that this address is no longer valid, so reading 445175383Sjhb * from it should trigger a SIGSEGV. 446175383Sjhb */ 447175383Sjhb c = page[getpagesize()]; 448175383Sjhb fprintf(stderr, "child: page 1: '%c'\n", c); 449175383Sjhb exit(0); 450175383Sjhb } 451289441Sngie 452289441Sngie if (wait(&status) < 0) 453289441Sngie atf_tc_fail("wait failed; errno=%d", errno); 454289441Sngie 455289441Sngie if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) 456289437Sngie atf_tc_fail("child terminated with status %x", status); 457175383Sjhb 458175383Sjhb /* Grow the object back to 2 pages. */ 459289441Sngie if (ftruncate(fd, getpagesize() * 2) < 0) 460289441Sngie atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 461175383Sjhb 462289441Sngie if (fstat(fd, &sb) < 0) 463289441Sngie atf_tc_fail("fstat(2) failed; errno=%d", errno); 464289441Sngie 465289441Sngie if (sb.st_size != getpagesize() * 2) 466289441Sngie atf_tc_fail("fourth resize failed (%d != %d)", 467289441Sngie (int)sb.st_size, getpagesize()); 468289441Sngie 469175383Sjhb /* 470175383Sjhb * Note that the mapping at 'page' for the second page is 471175383Sjhb * still valid, and now that the shm object has been grown 472175383Sjhb * back up to 2 pages, there is now memory backing this page 473175383Sjhb * so the read will work. However, the data should be zero 474175383Sjhb * rather than '2' as the old data was thrown away when the 475175383Sjhb * object was shrunk and the new pages when an object are 476175383Sjhb * grown are zero-filled. 477175383Sjhb */ 478289441Sngie if (page[getpagesize()] != 0) 479289441Sngie atf_tc_fail("invalid data at %d: %x != 0", 480289441Sngie getpagesize(), (int)page[getpagesize()]); 481175383Sjhb 482175383Sjhb close(fd); 483175383Sjhb} 484175383Sjhb 485289437Sngie/* Signal handler which does nothing. */ 486289437Sngiestatic void 487289437Sngieignoreit(int sig __unused) 488175383Sjhb{ 489289437Sngie ; 490289437Sngie} 491175383Sjhb 492289437SngieATF_TC_WITHOUT_HEAD(shm_functionality_across_fork); 493289437SngieATF_TC_BODY(shm_functionality_across_fork, tc) 494289437Sngie{ 495289437Sngie char *cp, c; 496289437Sngie int error, desc, rv; 497289437Sngie long scval; 498289437Sngie sigset_t ss; 499289437Sngie struct sigaction sa; 500289437Sngie void *region; 501289437Sngie size_t i, psize; 502289437Sngie 503289437Sngie#ifndef _POSIX_SHARED_MEMORY_OBJECTS 504289437Sngie printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 505289437Sngie#else 506289437Sngie printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 507289437Sngie (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 508289437Sngie if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 509289437Sngie printf("***Indicates this feature may be unsupported!\n"); 510289437Sngie#endif 511289437Sngie errno = 0; 512289437Sngie scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 513289437Sngie if (scval == -1 && errno != 0) { 514289437Sngie atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; " 515289437Sngie "errno=%d", errno); 516289437Sngie } else { 517289437Sngie printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 518289437Sngie scval); 519289437Sngie if (scval == -1) 520289437Sngie printf("***Indicates this feature is unsupported!\n"); 521289437Sngie } 522289437Sngie 523289437Sngie errno = 0; 524289437Sngie scval = sysconf(_SC_PAGESIZE); 525289437Sngie if (scval == -1 && errno != 0) { 526289437Sngie atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno); 527289437Sngie } else if (scval <= 0 || (size_t)psize != psize) { 528289437Sngie fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld", 529289437Sngie scval); 530289437Sngie psize = 4096; 531289437Sngie } else { 532289437Sngie printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 533289437Sngie psize = scval; 534289437Sngie } 535289437Sngie 536289437Sngie gen_test_path(); 537289437Sngie desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600); 538289437Sngie 539289437Sngie ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno); 540289437Sngie ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 541289437Sngie "shm_unlink failed; errno=%d", errno); 542289437Sngie ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1, 543289437Sngie "ftruncate failed; errno=%d", errno); 544289437Sngie 545289437Sngie region = mmap((void *)0, psize, PROT_READ | PROT_WRITE, MAP_SHARED, 546289437Sngie desc, (off_t)0); 547289437Sngie ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno); 548289437Sngie memset(region, '\377', psize); 549289437Sngie 550289437Sngie sa.sa_flags = 0; 551289437Sngie sa.sa_handler = ignoreit; 552289437Sngie sigemptyset(&sa.sa_mask); 553289437Sngie ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0, 554289437Sngie "sigaction failed; errno=%d", errno); 555289437Sngie 556289437Sngie sigemptyset(&ss); 557289437Sngie sigaddset(&ss, SIGUSR1); 558289437Sngie ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0, 559289437Sngie "sigprocmask failed; errno=%d", errno); 560289437Sngie 561289437Sngie rv = fork(); 562289437Sngie ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno); 563289437Sngie if (rv == 0) { 564289437Sngie sigemptyset(&ss); 565289437Sngie sigsuspend(&ss); 566289437Sngie 567289437Sngie for (cp = region; cp < (char *)region + psize; cp++) { 568289437Sngie if (*cp != '\151') 569289437Sngie _exit(1); 570289437Sngie } 571289437Sngie if (lseek(desc, 0, SEEK_SET) == -1) 572289437Sngie _exit(1); 573289437Sngie for (i = 0; i < psize; i++) { 574289437Sngie error = read(desc, &c, 1); 575289437Sngie if (c != '\151') 576289437Sngie _exit(1); 577289437Sngie } 578289437Sngie _exit(0); 579289437Sngie } else { 580289437Sngie int status; 581289437Sngie 582289437Sngie memset(region, '\151', psize - 2); 583289437Sngie error = pwrite(desc, region, 2, psize - 2); 584289437Sngie if (error != 2) { 585289437Sngie if (error >= 0) 586289437Sngie atf_tc_fail("short write; %d bytes written", 587289437Sngie error); 588289437Sngie else 589289437Sngie atf_tc_fail("shmfd write"); 590289437Sngie } 591289437Sngie kill(rv, SIGUSR1); 592289437Sngie waitpid(rv, &status, 0); 593289437Sngie 594289437Sngie if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 595289437Sngie printf("Functionality test successful\n"); 596289437Sngie } else if (WIFEXITED(status)) { 597289437Sngie atf_tc_fail("Child process exited with status %d", 598289437Sngie WEXITSTATUS(status)); 599289437Sngie } else { 600289437Sngie atf_tc_fail("Child process terminated with %s", 601289437Sngie strsignal(WTERMSIG(status))); 602289437Sngie } 603289437Sngie } 604175383Sjhb} 605289437Sngie 606289437SngieATF_TP_ADD_TCS(tp) 607289437Sngie{ 608289437Sngie 609289437Sngie ATF_TP_ADD_TC(tp, remap_object); 610289437Sngie ATF_TP_ADD_TC(tp, reopen_object); 611289437Sngie ATF_TP_ADD_TC(tp, readonly_mmap_write); 612289437Sngie ATF_TP_ADD_TC(tp, open_after_link); 613289437Sngie ATF_TP_ADD_TC(tp, open_invalid_path); 614289437Sngie ATF_TP_ADD_TC(tp, open_write_only); 615289437Sngie ATF_TP_ADD_TC(tp, open_extra_flags); 616289437Sngie ATF_TP_ADD_TC(tp, open_anon); 617289437Sngie ATF_TP_ADD_TC(tp, open_anon_readonly); 618289437Sngie ATF_TP_ADD_TC(tp, open_bad_path_pointer); 619289437Sngie ATF_TP_ADD_TC(tp, open_path_too_long); 620289437Sngie ATF_TP_ADD_TC(tp, open_nonexisting_object); 621289437Sngie ATF_TP_ADD_TC(tp, open_create_existing_object); 622289437Sngie ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 623289437Sngie ATF_TP_ADD_TC(tp, trunc_resets_object); 624289437Sngie ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 625289437Sngie ATF_TP_ADD_TC(tp, unlink_path_too_long); 626289437Sngie ATF_TP_ADD_TC(tp, object_resize); 627289437Sngie 628289437Sngie return (atf_no_error()); 629289437Sngie} 630