14fdc3d75SEnji Cooper /*- 24fdc3d75SEnji Cooper * Copyright (c) 2006 Robert N. M. Watson 34fdc3d75SEnji Cooper * All rights reserved. 44fdc3d75SEnji Cooper * 54fdc3d75SEnji Cooper * Redistribution and use in source and binary forms, with or without 64fdc3d75SEnji Cooper * modification, are permitted provided that the following conditions 74fdc3d75SEnji Cooper * are met: 84fdc3d75SEnji Cooper * 1. Redistributions of source code must retain the above copyright 94fdc3d75SEnji Cooper * notice, this list of conditions and the following disclaimer. 104fdc3d75SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 114fdc3d75SEnji Cooper * notice, this list of conditions and the following disclaimer in the 124fdc3d75SEnji Cooper * documentation and/or other materials provided with the distribution. 134fdc3d75SEnji Cooper * 144fdc3d75SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154fdc3d75SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164fdc3d75SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 174fdc3d75SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184fdc3d75SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194fdc3d75SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204fdc3d75SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214fdc3d75SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224fdc3d75SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234fdc3d75SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244fdc3d75SEnji Cooper * SUCH DAMAGE. 254fdc3d75SEnji Cooper */ 264fdc3d75SEnji Cooper 274fdc3d75SEnji Cooper #include <sys/cdefs.h> 284fdc3d75SEnji Cooper __FBSDID("$FreeBSD$"); 294fdc3d75SEnji Cooper 304fdc3d75SEnji Cooper #include <sys/param.h> 314fdc3d75SEnji Cooper #include <sys/mman.h> 324fdc3d75SEnji Cooper #include <sys/resource.h> 334fdc3d75SEnji Cooper #include <sys/stat.h> 344fdc3d75SEnji Cooper #include <sys/syscall.h> 354fdc3d75SEnji Cooper #include <sys/wait.h> 364fdc3d75SEnji Cooper 374fdc3d75SEnji Cooper #include <errno.h> 384fdc3d75SEnji Cooper #include <fcntl.h> 394fdc3d75SEnji Cooper #include <signal.h> 404fdc3d75SEnji Cooper #include <stdio.h> 414fdc3d75SEnji Cooper #include <stdlib.h> 424fdc3d75SEnji Cooper #include <string.h> 434fdc3d75SEnji Cooper #include <unistd.h> 444fdc3d75SEnji Cooper 454fdc3d75SEnji Cooper #include <atf-c.h> 464fdc3d75SEnji Cooper 474fdc3d75SEnji Cooper #define TEST_PATH_LEN 256 484fdc3d75SEnji Cooper static char test_path[TEST_PATH_LEN]; 494fdc3d75SEnji Cooper 504fdc3d75SEnji Cooper static void 514fdc3d75SEnji Cooper gen_test_path(void) 524fdc3d75SEnji Cooper { 534fdc3d75SEnji Cooper 5494ebd6f5SEnji Cooper snprintf(test_path, sizeof(test_path), "%s/tmp.XXXXXX", 5594ebd6f5SEnji Cooper getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR")); 564fdc3d75SEnji Cooper test_path[sizeof(test_path) - 1] = '\0'; 574fdc3d75SEnji Cooper ATF_REQUIRE_MSG(mkstemp(test_path) != -1, 584fdc3d75SEnji Cooper "mkstemp failed; errno=%d", errno); 594fdc3d75SEnji Cooper ATF_REQUIRE_MSG(unlink(test_path) == 0, 604fdc3d75SEnji Cooper "unlink failed; errno=%d", errno); 614fdc3d75SEnji Cooper } 624fdc3d75SEnji Cooper 634fdc3d75SEnji Cooper /* 644fdc3d75SEnji Cooper * Attempt a shm_open() that should fail with an expected error of 'error'. 654fdc3d75SEnji Cooper */ 664fdc3d75SEnji Cooper static void 674fdc3d75SEnji Cooper shm_open_should_fail(const char *path, int flags, mode_t mode, int error) 684fdc3d75SEnji Cooper { 694fdc3d75SEnji Cooper int fd; 704fdc3d75SEnji Cooper 714fdc3d75SEnji Cooper fd = shm_open(path, flags, mode); 724fdc3d75SEnji Cooper ATF_CHECK_MSG(fd == -1, "shm_open didn't fail"); 734fdc3d75SEnji Cooper ATF_CHECK_MSG(error == errno, 744fdc3d75SEnji Cooper "shm_open didn't fail with expected errno; errno=%d; expected " 754fdc3d75SEnji Cooper "errno=%d", errno, error); 764fdc3d75SEnji Cooper } 774fdc3d75SEnji Cooper 784fdc3d75SEnji Cooper /* 794fdc3d75SEnji Cooper * Attempt a shm_unlink() that should fail with an expected error of 'error'. 804fdc3d75SEnji Cooper */ 814fdc3d75SEnji Cooper static void 824fdc3d75SEnji Cooper shm_unlink_should_fail(const char *path, int error) 834fdc3d75SEnji Cooper { 844fdc3d75SEnji Cooper 854fdc3d75SEnji Cooper ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail"); 864fdc3d75SEnji Cooper ATF_CHECK_MSG(error == errno, 874fdc3d75SEnji Cooper "shm_unlink didn't fail with expected errno; errno=%d; expected " 884fdc3d75SEnji Cooper "errno=%d", errno, error); 894fdc3d75SEnji Cooper } 904fdc3d75SEnji Cooper 914fdc3d75SEnji Cooper /* 924fdc3d75SEnji Cooper * Open the test object and write '1' to the first byte. Returns valid fd 934fdc3d75SEnji Cooper * on success and -1 on failure. 944fdc3d75SEnji Cooper */ 954fdc3d75SEnji Cooper static int 964fdc3d75SEnji Cooper scribble_object(void) 974fdc3d75SEnji Cooper { 984fdc3d75SEnji Cooper char *page; 9994ebd6f5SEnji Cooper int fd, pagesize; 1004fdc3d75SEnji Cooper 1014fdc3d75SEnji Cooper gen_test_path(); 1024fdc3d75SEnji Cooper 10394ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 10494ebd6f5SEnji Cooper 1054fdc3d75SEnji Cooper fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777); 1064fdc3d75SEnji Cooper if (fd < 0 && errno == EEXIST) { 1074fdc3d75SEnji Cooper if (shm_unlink(test_path) < 0) 1084fdc3d75SEnji Cooper atf_tc_fail("shm_unlink"); 1094fdc3d75SEnji Cooper fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 1104fdc3d75SEnji Cooper } 1114fdc3d75SEnji Cooper if (fd < 0) 1124fdc3d75SEnji Cooper atf_tc_fail("shm_open failed; errno=%d", errno); 11394ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 1144fdc3d75SEnji Cooper atf_tc_fail("ftruncate failed; errno=%d", errno); 1154fdc3d75SEnji Cooper 11694ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1174fdc3d75SEnji Cooper if (page == MAP_FAILED) 1184fdc3d75SEnji Cooper atf_tc_fail("mmap failed; errno=%d", errno); 1194fdc3d75SEnji Cooper 1204fdc3d75SEnji Cooper page[0] = '1'; 12194ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 12294ebd6f5SEnji Cooper errno); 1234fdc3d75SEnji Cooper 1244fdc3d75SEnji Cooper return (fd); 1254fdc3d75SEnji Cooper } 1264fdc3d75SEnji Cooper 1274fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(remap_object); 1284fdc3d75SEnji Cooper ATF_TC_BODY(remap_object, tc) 1294fdc3d75SEnji Cooper { 1304fdc3d75SEnji Cooper char *page; 13194ebd6f5SEnji Cooper int fd, pagesize; 13294ebd6f5SEnji Cooper 13394ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 1344fdc3d75SEnji Cooper 1354fdc3d75SEnji Cooper fd = scribble_object(); 1364fdc3d75SEnji Cooper 13794ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1384fdc3d75SEnji Cooper if (page == MAP_FAILED) 1394fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 1404fdc3d75SEnji Cooper 1414fdc3d75SEnji Cooper if (page[0] != '1') 1424fdc3d75SEnji Cooper atf_tc_fail("missing data ('%c' != '1')", page[0]); 1434fdc3d75SEnji Cooper 1444fdc3d75SEnji Cooper close(fd); 14594ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 14694ebd6f5SEnji Cooper errno); 1474fdc3d75SEnji Cooper 1484fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 1494fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 1504fdc3d75SEnji Cooper } 1514fdc3d75SEnji Cooper 1524fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(reopen_object); 1534fdc3d75SEnji Cooper ATF_TC_BODY(reopen_object, tc) 1544fdc3d75SEnji Cooper { 1554fdc3d75SEnji Cooper char *page; 15694ebd6f5SEnji Cooper int fd, pagesize; 15794ebd6f5SEnji Cooper 15894ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 1594fdc3d75SEnji Cooper 1604fdc3d75SEnji Cooper fd = scribble_object(); 1614fdc3d75SEnji Cooper close(fd); 1624fdc3d75SEnji Cooper 1634fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY, 0777); 1644fdc3d75SEnji Cooper if (fd < 0) 1654fdc3d75SEnji Cooper atf_tc_fail("shm_open(2) failed; errno=%d", errno); 1664fdc3d75SEnji Cooper 16794ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 1684fdc3d75SEnji Cooper if (page == MAP_FAILED) 1694fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 1704fdc3d75SEnji Cooper 1714fdc3d75SEnji Cooper if (page[0] != '1') 1724fdc3d75SEnji Cooper atf_tc_fail("missing data ('%c' != '1')", page[0]); 1734fdc3d75SEnji Cooper 17494ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 17594ebd6f5SEnji Cooper errno); 1764fdc3d75SEnji Cooper close(fd); 1774fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 1784fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 1794fdc3d75SEnji Cooper } 1804fdc3d75SEnji Cooper 1814fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(readonly_mmap_write); 1824fdc3d75SEnji Cooper ATF_TC_BODY(readonly_mmap_write, tc) 1834fdc3d75SEnji Cooper { 1844fdc3d75SEnji Cooper char *page; 18594ebd6f5SEnji Cooper int fd, pagesize; 18694ebd6f5SEnji Cooper 18794ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 1884fdc3d75SEnji Cooper 1894fdc3d75SEnji Cooper gen_test_path(); 1904fdc3d75SEnji Cooper 1914fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 1924fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 1934fdc3d75SEnji Cooper 1944fdc3d75SEnji Cooper /* PROT_WRITE should fail with EACCES. */ 19594ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1964fdc3d75SEnji Cooper if (page != MAP_FAILED) 1974fdc3d75SEnji Cooper atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly"); 1984fdc3d75SEnji Cooper 1994fdc3d75SEnji Cooper if (errno != EACCES) 2004fdc3d75SEnji Cooper atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; " 2014fdc3d75SEnji Cooper "errno=%d", errno); 2024fdc3d75SEnji Cooper 2034fdc3d75SEnji Cooper close(fd); 2044fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 2054fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 2064fdc3d75SEnji Cooper } 2074fdc3d75SEnji Cooper 2084fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_after_link); 2094fdc3d75SEnji Cooper ATF_TC_BODY(open_after_link, tc) 2104fdc3d75SEnji Cooper { 2114fdc3d75SEnji Cooper int fd; 2124fdc3d75SEnji Cooper 2134fdc3d75SEnji Cooper gen_test_path(); 2144fdc3d75SEnji Cooper 2154fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 2164fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 2174fdc3d75SEnji Cooper close(fd); 2184fdc3d75SEnji Cooper 2194fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d", 2204fdc3d75SEnji Cooper errno); 2214fdc3d75SEnji Cooper 2224fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT); 2234fdc3d75SEnji Cooper } 2244fdc3d75SEnji Cooper 2254fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_invalid_path); 2264fdc3d75SEnji Cooper ATF_TC_BODY(open_invalid_path, tc) 2274fdc3d75SEnji Cooper { 2284fdc3d75SEnji Cooper 2294fdc3d75SEnji Cooper shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL); 2304fdc3d75SEnji Cooper } 2314fdc3d75SEnji Cooper 2324fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_write_only); 2334fdc3d75SEnji Cooper ATF_TC_BODY(open_write_only, tc) 2344fdc3d75SEnji Cooper { 2354fdc3d75SEnji Cooper 2364fdc3d75SEnji Cooper gen_test_path(); 2374fdc3d75SEnji Cooper 2384fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL); 2394fdc3d75SEnji Cooper } 2404fdc3d75SEnji Cooper 2414fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_extra_flags); 2424fdc3d75SEnji Cooper ATF_TC_BODY(open_extra_flags, tc) 2434fdc3d75SEnji Cooper { 2444fdc3d75SEnji Cooper 2454fdc3d75SEnji Cooper gen_test_path(); 2464fdc3d75SEnji Cooper 2474fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL); 2484fdc3d75SEnji Cooper } 2494fdc3d75SEnji Cooper 2504fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon); 2514fdc3d75SEnji Cooper ATF_TC_BODY(open_anon, tc) 2524fdc3d75SEnji Cooper { 2534fdc3d75SEnji Cooper int fd; 2544fdc3d75SEnji Cooper 2554fdc3d75SEnji Cooper fd = shm_open(SHM_ANON, O_RDWR, 0777); 2564fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 2574fdc3d75SEnji Cooper close(fd); 2584fdc3d75SEnji Cooper } 2594fdc3d75SEnji Cooper 2604fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon_readonly); 2614fdc3d75SEnji Cooper ATF_TC_BODY(open_anon_readonly, tc) 2624fdc3d75SEnji Cooper { 2634fdc3d75SEnji Cooper 2644fdc3d75SEnji Cooper shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); 2654fdc3d75SEnji Cooper } 2664fdc3d75SEnji Cooper 2674fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_bad_path_pointer); 2684fdc3d75SEnji Cooper ATF_TC_BODY(open_bad_path_pointer, tc) 2694fdc3d75SEnji Cooper { 2704fdc3d75SEnji Cooper 2714fdc3d75SEnji Cooper shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT); 2724fdc3d75SEnji Cooper } 2734fdc3d75SEnji Cooper 2744fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_path_too_long); 2754fdc3d75SEnji Cooper ATF_TC_BODY(open_path_too_long, tc) 2764fdc3d75SEnji Cooper { 2774fdc3d75SEnji Cooper char *page; 2784fdc3d75SEnji Cooper 2794fdc3d75SEnji Cooper page = malloc(MAXPATHLEN + 1); 2804fdc3d75SEnji Cooper memset(page, 'a', MAXPATHLEN); 2814fdc3d75SEnji Cooper page[MAXPATHLEN] = '\0'; 2824fdc3d75SEnji Cooper shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG); 2834fdc3d75SEnji Cooper free(page); 2844fdc3d75SEnji Cooper } 2854fdc3d75SEnji Cooper 2864fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_nonexisting_object); 2874fdc3d75SEnji Cooper ATF_TC_BODY(open_nonexisting_object, tc) 2884fdc3d75SEnji Cooper { 2894fdc3d75SEnji Cooper 2904fdc3d75SEnji Cooper shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT); 2914fdc3d75SEnji Cooper } 2924fdc3d75SEnji Cooper 2934fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_create_existing_object); 2944fdc3d75SEnji Cooper ATF_TC_BODY(open_create_existing_object, tc) 2954fdc3d75SEnji Cooper { 2964fdc3d75SEnji Cooper int fd; 2974fdc3d75SEnji Cooper 2984fdc3d75SEnji Cooper gen_test_path(); 2994fdc3d75SEnji Cooper 3004fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777); 3014fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 3024fdc3d75SEnji Cooper close(fd); 3034fdc3d75SEnji Cooper 3044fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL, 3054fdc3d75SEnji Cooper 0777, EEXIST); 3064fdc3d75SEnji Cooper 3074fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 3084fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 3094fdc3d75SEnji Cooper } 3104fdc3d75SEnji Cooper 3114fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(trunc_resets_object); 3124fdc3d75SEnji Cooper ATF_TC_BODY(trunc_resets_object, tc) 3134fdc3d75SEnji Cooper { 3144fdc3d75SEnji Cooper struct stat sb; 3154fdc3d75SEnji Cooper int fd; 3164fdc3d75SEnji Cooper 3174fdc3d75SEnji Cooper gen_test_path(); 3184fdc3d75SEnji Cooper 3194fdc3d75SEnji Cooper /* Create object and set size to 1024. */ 3204fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDWR | O_CREAT, 0777); 3214fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 3224fdc3d75SEnji Cooper ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1, 3234fdc3d75SEnji Cooper "ftruncate failed; errno=%d", errno); 3244fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 3254fdc3d75SEnji Cooper "fstat(1) failed; errno=%d", errno); 3264fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size); 3274fdc3d75SEnji Cooper close(fd); 3284fdc3d75SEnji Cooper 3294fdc3d75SEnji Cooper /* Open with O_TRUNC which should reset size to 0. */ 3304fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777); 3314fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno); 3324fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 3334fdc3d75SEnji Cooper "fstat(2) failed; errno=%d", errno); 3344fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sb.st_size == 0, 3354fdc3d75SEnji Cooper "size was not 0 after truncation: %d", (int)sb.st_size); 3364fdc3d75SEnji Cooper close(fd); 3374fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 3384fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 3394fdc3d75SEnji Cooper } 3404fdc3d75SEnji Cooper 3414fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer); 3424fdc3d75SEnji Cooper ATF_TC_BODY(unlink_bad_path_pointer, tc) 3434fdc3d75SEnji Cooper { 3444fdc3d75SEnji Cooper 3454fdc3d75SEnji Cooper shm_unlink_should_fail((char *)1024, EFAULT); 3464fdc3d75SEnji Cooper } 3474fdc3d75SEnji Cooper 3484fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_path_too_long); 3494fdc3d75SEnji Cooper ATF_TC_BODY(unlink_path_too_long, tc) 3504fdc3d75SEnji Cooper { 3514fdc3d75SEnji Cooper char *page; 3524fdc3d75SEnji Cooper 3534fdc3d75SEnji Cooper page = malloc(MAXPATHLEN + 1); 3544fdc3d75SEnji Cooper memset(page, 'a', MAXPATHLEN); 3554fdc3d75SEnji Cooper page[MAXPATHLEN] = '\0'; 3564fdc3d75SEnji Cooper shm_unlink_should_fail(page, ENAMETOOLONG); 3574fdc3d75SEnji Cooper free(page); 3584fdc3d75SEnji Cooper } 3594fdc3d75SEnji Cooper 3604fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(object_resize); 3614fdc3d75SEnji Cooper ATF_TC_BODY(object_resize, tc) 3624fdc3d75SEnji Cooper { 3634fdc3d75SEnji Cooper pid_t pid; 3644fdc3d75SEnji Cooper struct stat sb; 36594ebd6f5SEnji Cooper char *page; 36694ebd6f5SEnji Cooper int fd, pagesize, status; 36794ebd6f5SEnji Cooper 36894ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 3694fdc3d75SEnji Cooper 3704fdc3d75SEnji Cooper /* Start off with a size of a single page. */ 3714fdc3d75SEnji Cooper fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777); 3724fdc3d75SEnji Cooper if (fd < 0) 3734fdc3d75SEnji Cooper atf_tc_fail("shm_open failed; errno=%d", errno); 3744fdc3d75SEnji Cooper 37594ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 3764fdc3d75SEnji Cooper atf_tc_fail("ftruncate(1) failed; errno=%d", errno); 3774fdc3d75SEnji Cooper 3784fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 3794fdc3d75SEnji Cooper atf_tc_fail("fstat(1) failed; errno=%d", errno); 3804fdc3d75SEnji Cooper 38194ebd6f5SEnji Cooper if (sb.st_size != pagesize) 3824fdc3d75SEnji Cooper atf_tc_fail("first resize failed (%d != %d)", 38394ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 3844fdc3d75SEnji Cooper 3854fdc3d75SEnji Cooper /* Write a '1' to the first byte. */ 38694ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 3874fdc3d75SEnji Cooper if (page == MAP_FAILED) 3884fdc3d75SEnji Cooper atf_tc_fail("mmap(1)"); 3894fdc3d75SEnji Cooper 3904fdc3d75SEnji Cooper page[0] = '1'; 3914fdc3d75SEnji Cooper 39294ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 39394ebd6f5SEnji Cooper errno); 3944fdc3d75SEnji Cooper 3954fdc3d75SEnji Cooper /* Grow the object to 2 pages. */ 39694ebd6f5SEnji Cooper if (ftruncate(fd, pagesize * 2) < 0) 3974fdc3d75SEnji Cooper atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 3984fdc3d75SEnji Cooper 3994fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 4004fdc3d75SEnji Cooper atf_tc_fail("fstat(2) failed; errno=%d", errno); 4014fdc3d75SEnji Cooper 40294ebd6f5SEnji Cooper if (sb.st_size != pagesize * 2) 4034fdc3d75SEnji Cooper atf_tc_fail("second resize failed (%d != %d)", 40494ebd6f5SEnji Cooper (int)sb.st_size, pagesize * 2); 4054fdc3d75SEnji Cooper 4064fdc3d75SEnji Cooper /* Check for '1' at the first byte. */ 40794ebd6f5SEnji Cooper page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 4084fdc3d75SEnji Cooper if (page == MAP_FAILED) 4094fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 4104fdc3d75SEnji Cooper 4114fdc3d75SEnji Cooper if (page[0] != '1') 4124fdc3d75SEnji Cooper atf_tc_fail("'%c' != '1'", page[0]); 4134fdc3d75SEnji Cooper 4144fdc3d75SEnji Cooper /* Write a '2' at the start of the second page. */ 41594ebd6f5SEnji Cooper page[pagesize] = '2'; 4164fdc3d75SEnji Cooper 4174fdc3d75SEnji Cooper /* Shrink the object back to 1 page. */ 41894ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 4194fdc3d75SEnji Cooper atf_tc_fail("ftruncate(3) failed; errno=%d", errno); 4204fdc3d75SEnji Cooper 4214fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 4224fdc3d75SEnji Cooper atf_tc_fail("fstat(3) failed; errno=%d", errno); 4234fdc3d75SEnji Cooper 42494ebd6f5SEnji Cooper if (sb.st_size != pagesize) 4254fdc3d75SEnji Cooper atf_tc_fail("third resize failed (%d != %d)", 42694ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 4274fdc3d75SEnji Cooper 4284fdc3d75SEnji Cooper /* 4294fdc3d75SEnji Cooper * Fork a child process to make sure the second page is no 4304fdc3d75SEnji Cooper * longer valid. 4314fdc3d75SEnji Cooper */ 4324fdc3d75SEnji Cooper pid = fork(); 4334fdc3d75SEnji Cooper if (pid == -1) 4344fdc3d75SEnji Cooper atf_tc_fail("fork failed; errno=%d", errno); 4354fdc3d75SEnji Cooper 4364fdc3d75SEnji Cooper if (pid == 0) { 4374fdc3d75SEnji Cooper struct rlimit lim; 4384fdc3d75SEnji Cooper char c; 4394fdc3d75SEnji Cooper 4404fdc3d75SEnji Cooper /* Don't generate a core dump. */ 44194ebd6f5SEnji Cooper ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0); 4424fdc3d75SEnji Cooper lim.rlim_cur = 0; 44394ebd6f5SEnji Cooper ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0); 4444fdc3d75SEnji Cooper 4454fdc3d75SEnji Cooper /* 4464fdc3d75SEnji Cooper * The previous ftruncate(2) shrunk the backing object 4474fdc3d75SEnji Cooper * so that this address is no longer valid, so reading 4484fdc3d75SEnji Cooper * from it should trigger a SIGSEGV. 4494fdc3d75SEnji Cooper */ 45094ebd6f5SEnji Cooper c = page[pagesize]; 4514fdc3d75SEnji Cooper fprintf(stderr, "child: page 1: '%c'\n", c); 4524fdc3d75SEnji Cooper exit(0); 4534fdc3d75SEnji Cooper } 4544fdc3d75SEnji Cooper 4554fdc3d75SEnji Cooper if (wait(&status) < 0) 4564fdc3d75SEnji Cooper atf_tc_fail("wait failed; errno=%d", errno); 4574fdc3d75SEnji Cooper 4584fdc3d75SEnji Cooper if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) 4594fdc3d75SEnji Cooper atf_tc_fail("child terminated with status %x", status); 4604fdc3d75SEnji Cooper 4614fdc3d75SEnji Cooper /* Grow the object back to 2 pages. */ 46294ebd6f5SEnji Cooper if (ftruncate(fd, pagesize * 2) < 0) 4634fdc3d75SEnji Cooper atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 4644fdc3d75SEnji Cooper 4654fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 4664fdc3d75SEnji Cooper atf_tc_fail("fstat(2) failed; errno=%d", errno); 4674fdc3d75SEnji Cooper 46894ebd6f5SEnji Cooper if (sb.st_size != pagesize * 2) 4694fdc3d75SEnji Cooper atf_tc_fail("fourth resize failed (%d != %d)", 47094ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 4714fdc3d75SEnji Cooper 4724fdc3d75SEnji Cooper /* 4734fdc3d75SEnji Cooper * Note that the mapping at 'page' for the second page is 4744fdc3d75SEnji Cooper * still valid, and now that the shm object has been grown 4754fdc3d75SEnji Cooper * back up to 2 pages, there is now memory backing this page 4764fdc3d75SEnji Cooper * so the read will work. However, the data should be zero 4774fdc3d75SEnji Cooper * rather than '2' as the old data was thrown away when the 4784fdc3d75SEnji Cooper * object was shrunk and the new pages when an object are 4794fdc3d75SEnji Cooper * grown are zero-filled. 4804fdc3d75SEnji Cooper */ 48194ebd6f5SEnji Cooper if (page[pagesize] != 0) 4824fdc3d75SEnji Cooper atf_tc_fail("invalid data at %d: %x != 0", 48394ebd6f5SEnji Cooper pagesize, (int)page[pagesize]); 4844fdc3d75SEnji Cooper 4854fdc3d75SEnji Cooper close(fd); 4864fdc3d75SEnji Cooper } 4874fdc3d75SEnji Cooper 4884fdc3d75SEnji Cooper /* Signal handler which does nothing. */ 4894fdc3d75SEnji Cooper static void 4904fdc3d75SEnji Cooper ignoreit(int sig __unused) 4914fdc3d75SEnji Cooper { 4924fdc3d75SEnji Cooper ; 4934fdc3d75SEnji Cooper } 4944fdc3d75SEnji Cooper 4954fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork); 4964fdc3d75SEnji Cooper ATF_TC_BODY(shm_functionality_across_fork, tc) 4974fdc3d75SEnji Cooper { 4984fdc3d75SEnji Cooper char *cp, c; 4994fdc3d75SEnji Cooper int error, desc, rv; 5004fdc3d75SEnji Cooper long scval; 5014fdc3d75SEnji Cooper sigset_t ss; 5024fdc3d75SEnji Cooper struct sigaction sa; 5034fdc3d75SEnji Cooper void *region; 5044fdc3d75SEnji Cooper size_t i, psize; 5054fdc3d75SEnji Cooper 5064fdc3d75SEnji Cooper #ifndef _POSIX_SHARED_MEMORY_OBJECTS 5074fdc3d75SEnji Cooper printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 5084fdc3d75SEnji Cooper #else 5094fdc3d75SEnji Cooper printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 5104fdc3d75SEnji Cooper (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 5114fdc3d75SEnji Cooper if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 5124fdc3d75SEnji Cooper printf("***Indicates this feature may be unsupported!\n"); 5134fdc3d75SEnji Cooper #endif 5144fdc3d75SEnji Cooper errno = 0; 5154fdc3d75SEnji Cooper scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 5164fdc3d75SEnji Cooper if (scval == -1 && errno != 0) { 5174fdc3d75SEnji Cooper atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; " 5184fdc3d75SEnji Cooper "errno=%d", errno); 5194fdc3d75SEnji Cooper } else { 5204fdc3d75SEnji Cooper printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 5214fdc3d75SEnji Cooper scval); 5224fdc3d75SEnji Cooper if (scval == -1) 5234fdc3d75SEnji Cooper printf("***Indicates this feature is unsupported!\n"); 5244fdc3d75SEnji Cooper } 5254fdc3d75SEnji Cooper 5264fdc3d75SEnji Cooper errno = 0; 5274fdc3d75SEnji Cooper scval = sysconf(_SC_PAGESIZE); 5284fdc3d75SEnji Cooper if (scval == -1 && errno != 0) { 5294fdc3d75SEnji Cooper atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno); 53094ebd6f5SEnji Cooper } else if (scval <= 0) { 5314fdc3d75SEnji Cooper fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld", 5324fdc3d75SEnji Cooper scval); 5334fdc3d75SEnji Cooper psize = 4096; 5344fdc3d75SEnji Cooper } else { 5354fdc3d75SEnji Cooper printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 5364fdc3d75SEnji Cooper psize = scval; 5374fdc3d75SEnji Cooper } 5384fdc3d75SEnji Cooper 5394fdc3d75SEnji Cooper gen_test_path(); 5404fdc3d75SEnji Cooper desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600); 5414fdc3d75SEnji Cooper 5424fdc3d75SEnji Cooper ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno); 5434fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 5444fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 5454fdc3d75SEnji Cooper ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1, 5464fdc3d75SEnji Cooper "ftruncate failed; errno=%d", errno); 5474fdc3d75SEnji Cooper 54894ebd6f5SEnji Cooper region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0); 5494fdc3d75SEnji Cooper ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno); 5504fdc3d75SEnji Cooper memset(region, '\377', psize); 5514fdc3d75SEnji Cooper 5524fdc3d75SEnji Cooper sa.sa_flags = 0; 5534fdc3d75SEnji Cooper sa.sa_handler = ignoreit; 5544fdc3d75SEnji Cooper sigemptyset(&sa.sa_mask); 5554fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0, 5564fdc3d75SEnji Cooper "sigaction failed; errno=%d", errno); 5574fdc3d75SEnji Cooper 5584fdc3d75SEnji Cooper sigemptyset(&ss); 5594fdc3d75SEnji Cooper sigaddset(&ss, SIGUSR1); 5604fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0, 5614fdc3d75SEnji Cooper "sigprocmask failed; errno=%d", errno); 5624fdc3d75SEnji Cooper 5634fdc3d75SEnji Cooper rv = fork(); 5644fdc3d75SEnji Cooper ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno); 5654fdc3d75SEnji Cooper if (rv == 0) { 5664fdc3d75SEnji Cooper sigemptyset(&ss); 5674fdc3d75SEnji Cooper sigsuspend(&ss); 5684fdc3d75SEnji Cooper 5694fdc3d75SEnji Cooper for (cp = region; cp < (char *)region + psize; cp++) { 5704fdc3d75SEnji Cooper if (*cp != '\151') 5714fdc3d75SEnji Cooper _exit(1); 5724fdc3d75SEnji Cooper } 5734fdc3d75SEnji Cooper if (lseek(desc, 0, SEEK_SET) == -1) 5744fdc3d75SEnji Cooper _exit(1); 5754fdc3d75SEnji Cooper for (i = 0; i < psize; i++) { 5764fdc3d75SEnji Cooper error = read(desc, &c, 1); 5774fdc3d75SEnji Cooper if (c != '\151') 5784fdc3d75SEnji Cooper _exit(1); 5794fdc3d75SEnji Cooper } 5804fdc3d75SEnji Cooper _exit(0); 5814fdc3d75SEnji Cooper } else { 5824fdc3d75SEnji Cooper int status; 5834fdc3d75SEnji Cooper 5844fdc3d75SEnji Cooper memset(region, '\151', psize - 2); 5854fdc3d75SEnji Cooper error = pwrite(desc, region, 2, psize - 2); 5864fdc3d75SEnji Cooper if (error != 2) { 5874fdc3d75SEnji Cooper if (error >= 0) 5884fdc3d75SEnji Cooper atf_tc_fail("short write; %d bytes written", 5894fdc3d75SEnji Cooper error); 5904fdc3d75SEnji Cooper else 5914fdc3d75SEnji Cooper atf_tc_fail("shmfd write"); 5924fdc3d75SEnji Cooper } 5934fdc3d75SEnji Cooper kill(rv, SIGUSR1); 5944fdc3d75SEnji Cooper waitpid(rv, &status, 0); 5954fdc3d75SEnji Cooper 5964fdc3d75SEnji Cooper if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 5974fdc3d75SEnji Cooper printf("Functionality test successful\n"); 5984fdc3d75SEnji Cooper } else if (WIFEXITED(status)) { 5994fdc3d75SEnji Cooper atf_tc_fail("Child process exited with status %d", 6004fdc3d75SEnji Cooper WEXITSTATUS(status)); 6014fdc3d75SEnji Cooper } else { 6024fdc3d75SEnji Cooper atf_tc_fail("Child process terminated with %s", 6034fdc3d75SEnji Cooper strsignal(WTERMSIG(status))); 6044fdc3d75SEnji Cooper } 6054fdc3d75SEnji Cooper } 60694ebd6f5SEnji Cooper 60794ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d", 60894ebd6f5SEnji Cooper errno); 60994ebd6f5SEnji Cooper shm_unlink(test_path); 6104fdc3d75SEnji Cooper } 6114fdc3d75SEnji Cooper 612*95aa96f3SKyle Evans ATF_TC_WITHOUT_HEAD(cloexec); 613*95aa96f3SKyle Evans ATF_TC_BODY(cloexec, tc) 614*95aa96f3SKyle Evans { 615*95aa96f3SKyle Evans int fd; 616*95aa96f3SKyle Evans 617*95aa96f3SKyle Evans gen_test_path(); 618*95aa96f3SKyle Evans 619*95aa96f3SKyle Evans /* shm_open(2) is required to set FD_CLOEXEC */ 620*95aa96f3SKyle Evans fd = shm_open(SHM_ANON, O_RDWR, 0777); 621*95aa96f3SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 622*95aa96f3SKyle Evans ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0); 623*95aa96f3SKyle Evans close(fd); 624*95aa96f3SKyle Evans 625*95aa96f3SKyle Evans /* Also make sure that named shm is correct */ 626*95aa96f3SKyle Evans fd = shm_open(test_path, O_CREAT | O_RDWR, 0600); 627*95aa96f3SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 628*95aa96f3SKyle Evans ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0); 629*95aa96f3SKyle Evans close(fd); 630*95aa96f3SKyle Evans } 631*95aa96f3SKyle Evans 632*95aa96f3SKyle Evans 6334fdc3d75SEnji Cooper ATF_TP_ADD_TCS(tp) 6344fdc3d75SEnji Cooper { 6354fdc3d75SEnji Cooper 6364fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, remap_object); 6374fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, reopen_object); 6384fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, readonly_mmap_write); 6394fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_after_link); 6404fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_invalid_path); 6414fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_write_only); 6424fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_extra_flags); 6434fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_anon); 6444fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_anon_readonly); 6454fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_bad_path_pointer); 6464fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_path_too_long); 6474fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_nonexisting_object); 6484fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_create_existing_object); 6494fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 6504fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, trunc_resets_object); 6514fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 6524fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, unlink_path_too_long); 6534fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, object_resize); 654*95aa96f3SKyle Evans ATF_TP_ADD_TC(tp, cloexec); 6554fdc3d75SEnji Cooper 6564fdc3d75SEnji Cooper return (atf_no_error()); 6574fdc3d75SEnji Cooper } 658