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 379afb12baSDavid Bright #include <ctype.h> 384fdc3d75SEnji Cooper #include <errno.h> 394fdc3d75SEnji Cooper #include <fcntl.h> 404fdc3d75SEnji Cooper #include <signal.h> 414fdc3d75SEnji Cooper #include <stdio.h> 424fdc3d75SEnji Cooper #include <stdlib.h> 434fdc3d75SEnji Cooper #include <string.h> 444fdc3d75SEnji Cooper #include <unistd.h> 454fdc3d75SEnji Cooper 464fdc3d75SEnji Cooper #include <atf-c.h> 474fdc3d75SEnji Cooper 484fdc3d75SEnji Cooper #define TEST_PATH_LEN 256 494fdc3d75SEnji Cooper static char test_path[TEST_PATH_LEN]; 509afb12baSDavid Bright static char test_path2[TEST_PATH_LEN]; 519afb12baSDavid Bright static unsigned int test_path_idx = 0; 529afb12baSDavid Bright 539afb12baSDavid Bright static void 549afb12baSDavid Bright gen_a_test_path(char *path) 559afb12baSDavid Bright { 569afb12baSDavid Bright snprintf(path, TEST_PATH_LEN, "%s/tmp.XXXXXX%d", 579afb12baSDavid Bright getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"), 589afb12baSDavid Bright test_path_idx); 599afb12baSDavid Bright 609afb12baSDavid Bright test_path_idx++; 619afb12baSDavid Bright 629afb12baSDavid Bright ATF_REQUIRE_MSG(mkstemp(path) != -1, 639afb12baSDavid Bright "mkstemp failed; errno=%d", errno); 649afb12baSDavid Bright ATF_REQUIRE_MSG(unlink(path) == 0, 659afb12baSDavid Bright "unlink failed; errno=%d", errno); 669afb12baSDavid Bright } 674fdc3d75SEnji Cooper 684fdc3d75SEnji Cooper static void 694fdc3d75SEnji Cooper gen_test_path(void) 704fdc3d75SEnji Cooper { 719afb12baSDavid Bright gen_a_test_path(test_path); 729afb12baSDavid Bright } 734fdc3d75SEnji Cooper 749afb12baSDavid Bright static void 759afb12baSDavid Bright gen_test_path2(void) 769afb12baSDavid Bright { 779afb12baSDavid Bright gen_a_test_path(test_path2); 784fdc3d75SEnji Cooper } 794fdc3d75SEnji Cooper 804fdc3d75SEnji Cooper /* 814fdc3d75SEnji Cooper * Attempt a shm_open() that should fail with an expected error of 'error'. 824fdc3d75SEnji Cooper */ 834fdc3d75SEnji Cooper static void 844fdc3d75SEnji Cooper shm_open_should_fail(const char *path, int flags, mode_t mode, int error) 854fdc3d75SEnji Cooper { 864fdc3d75SEnji Cooper int fd; 874fdc3d75SEnji Cooper 884fdc3d75SEnji Cooper fd = shm_open(path, flags, mode); 894fdc3d75SEnji Cooper ATF_CHECK_MSG(fd == -1, "shm_open didn't fail"); 904fdc3d75SEnji Cooper ATF_CHECK_MSG(error == errno, 914fdc3d75SEnji Cooper "shm_open didn't fail with expected errno; errno=%d; expected " 924fdc3d75SEnji Cooper "errno=%d", errno, error); 934fdc3d75SEnji Cooper } 944fdc3d75SEnji Cooper 954fdc3d75SEnji Cooper /* 964fdc3d75SEnji Cooper * Attempt a shm_unlink() that should fail with an expected error of 'error'. 974fdc3d75SEnji Cooper */ 984fdc3d75SEnji Cooper static void 994fdc3d75SEnji Cooper shm_unlink_should_fail(const char *path, int error) 1004fdc3d75SEnji Cooper { 1014fdc3d75SEnji Cooper 1024fdc3d75SEnji Cooper ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail"); 1034fdc3d75SEnji Cooper ATF_CHECK_MSG(error == errno, 1044fdc3d75SEnji Cooper "shm_unlink didn't fail with expected errno; errno=%d; expected " 1054fdc3d75SEnji Cooper "errno=%d", errno, error); 1064fdc3d75SEnji Cooper } 1074fdc3d75SEnji Cooper 1084fdc3d75SEnji Cooper /* 1099afb12baSDavid Bright * Open the test object and write a value to the first byte. Returns valid fd 1104fdc3d75SEnji Cooper * on success and -1 on failure. 1114fdc3d75SEnji Cooper */ 1124fdc3d75SEnji Cooper static int 1139afb12baSDavid Bright scribble_object(const char *path, char value) 1144fdc3d75SEnji Cooper { 1154fdc3d75SEnji Cooper char *page; 11694ebd6f5SEnji Cooper int fd, pagesize; 1174fdc3d75SEnji Cooper 11894ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 11994ebd6f5SEnji Cooper 1209afb12baSDavid Bright fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777); 1214fdc3d75SEnji Cooper if (fd < 0 && errno == EEXIST) { 1224fdc3d75SEnji Cooper if (shm_unlink(test_path) < 0) 1234fdc3d75SEnji Cooper atf_tc_fail("shm_unlink"); 1244fdc3d75SEnji Cooper fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 1254fdc3d75SEnji Cooper } 1264fdc3d75SEnji Cooper if (fd < 0) 1274fdc3d75SEnji Cooper atf_tc_fail("shm_open failed; errno=%d", errno); 12894ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 1294fdc3d75SEnji Cooper atf_tc_fail("ftruncate failed; errno=%d", errno); 1304fdc3d75SEnji Cooper 13194ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1324fdc3d75SEnji Cooper if (page == MAP_FAILED) 1334fdc3d75SEnji Cooper atf_tc_fail("mmap failed; errno=%d", errno); 1344fdc3d75SEnji Cooper 1359afb12baSDavid Bright page[0] = value; 13694ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 13794ebd6f5SEnji Cooper errno); 1384fdc3d75SEnji Cooper 1394fdc3d75SEnji Cooper return (fd); 1404fdc3d75SEnji Cooper } 1414fdc3d75SEnji Cooper 1429afb12baSDavid Bright /* 1439afb12baSDavid Bright * Fail the test case if the 'path' does not refer to an shm whose first byte 1449afb12baSDavid Bright * is equal to expected_value 1459afb12baSDavid Bright */ 1469afb12baSDavid Bright static void 1479afb12baSDavid Bright verify_object(const char *path, char expected_value) 1489afb12baSDavid Bright { 1499afb12baSDavid Bright int fd; 1509afb12baSDavid Bright int pagesize; 1519afb12baSDavid Bright char *page; 1529afb12baSDavid Bright 1539afb12baSDavid Bright ATF_REQUIRE(0 < (pagesize = getpagesize())); 1549afb12baSDavid Bright 1559afb12baSDavid Bright fd = shm_open(path, O_RDONLY, 0777); 1569afb12baSDavid Bright if (fd < 0) 1579afb12baSDavid Bright atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s", 1589afb12baSDavid Bright errno, path); 1599afb12baSDavid Bright 1609afb12baSDavid Bright page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 1619afb12baSDavid Bright if (page == MAP_FAILED) 1629afb12baSDavid Bright atf_tc_fail("mmap(1)"); 1639afb12baSDavid Bright if (page[0] != expected_value) 1649afb12baSDavid Bright atf_tc_fail("Renamed object has incorrect value; has" 1659afb12baSDavid Bright "%d (0x%x, '%c'), expected %d (0x%x, '%c')\n", 1669afb12baSDavid Bright page[0], page[0], isprint(page[0]) ? page[0] : ' ', 1679afb12baSDavid Bright expected_value, expected_value, 1689afb12baSDavid Bright isprint(expected_value) ? expected_value : ' '); 1699afb12baSDavid Bright ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 1709afb12baSDavid Bright errno); 1719afb12baSDavid Bright close(fd); 1729afb12baSDavid Bright } 1739afb12baSDavid Bright 1744fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(remap_object); 1754fdc3d75SEnji Cooper ATF_TC_BODY(remap_object, tc) 1764fdc3d75SEnji Cooper { 1774fdc3d75SEnji Cooper char *page; 17894ebd6f5SEnji Cooper int fd, pagesize; 17994ebd6f5SEnji Cooper 18094ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 1814fdc3d75SEnji Cooper 1829afb12baSDavid Bright gen_test_path(); 1839afb12baSDavid Bright fd = scribble_object(test_path, '1'); 1844fdc3d75SEnji Cooper 18594ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1864fdc3d75SEnji Cooper if (page == MAP_FAILED) 1874fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 1884fdc3d75SEnji Cooper 1894fdc3d75SEnji Cooper if (page[0] != '1') 1904fdc3d75SEnji Cooper atf_tc_fail("missing data ('%c' != '1')", page[0]); 1914fdc3d75SEnji Cooper 1924fdc3d75SEnji Cooper close(fd); 19394ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 19494ebd6f5SEnji Cooper errno); 1954fdc3d75SEnji Cooper 1964fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 1974fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 1984fdc3d75SEnji Cooper } 1994fdc3d75SEnji Cooper 2009afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_from_anon); 2019afb12baSDavid Bright ATF_TC_BODY(rename_from_anon, tc) 2029afb12baSDavid Bright { 2039afb12baSDavid Bright int rc; 2049afb12baSDavid Bright 2059afb12baSDavid Bright gen_test_path(); 2069afb12baSDavid Bright rc = shm_rename(SHM_ANON, test_path, 0); 2079afb12baSDavid Bright if (rc != -1) 2089afb12baSDavid Bright atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly"); 2099afb12baSDavid Bright } 2109afb12baSDavid Bright 2119afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_path_pointer); 2129afb12baSDavid Bright ATF_TC_BODY(rename_bad_path_pointer, tc) 2139afb12baSDavid Bright { 2149afb12baSDavid Bright const char *bad_path; 2159afb12baSDavid Bright int rc; 2169afb12baSDavid Bright 2179afb12baSDavid Bright bad_path = (const char *)0x1; 2189afb12baSDavid Bright 2199afb12baSDavid Bright gen_test_path(); 2209afb12baSDavid Bright rc = shm_rename(test_path, bad_path, 0); 2219afb12baSDavid Bright if (rc != -1) 2229afb12baSDavid Bright atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); 2239afb12baSDavid Bright 2249afb12baSDavid Bright rc = shm_rename(bad_path, test_path, 0); 2259afb12baSDavid Bright if (rc != -1) 2269afb12baSDavid Bright atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); 2279afb12baSDavid Bright } 2289afb12baSDavid Bright 2299afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_from_nonexisting); 2309afb12baSDavid Bright ATF_TC_BODY(rename_from_nonexisting, tc) 2319afb12baSDavid Bright { 2329afb12baSDavid Bright int rc; 2339afb12baSDavid Bright 2349afb12baSDavid Bright gen_test_path(); 2359afb12baSDavid Bright rc = shm_rename(test_path, test_path2, 0); 2369afb12baSDavid Bright if (rc != -1) 2379afb12baSDavid Bright atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); 2389afb12baSDavid Bright 2399afb12baSDavid Bright if (errno != ENOENT) 2409afb12baSDavid Bright atf_tc_fail("Expected ENOENT to rename of nonexistent shm"); 2419afb12baSDavid Bright } 2429afb12baSDavid Bright 2439afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_anon); 2449afb12baSDavid Bright ATF_TC_BODY(rename_to_anon, tc) 2459afb12baSDavid Bright { 2469afb12baSDavid Bright int rc; 2479afb12baSDavid Bright 2489afb12baSDavid Bright gen_test_path(); 2499afb12baSDavid Bright rc = shm_rename(test_path, SHM_ANON, 0); 2509afb12baSDavid Bright if (rc != -1) 2519afb12baSDavid Bright atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly"); 2529afb12baSDavid Bright } 2539afb12baSDavid Bright 2549afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_replace); 2559afb12baSDavid Bright ATF_TC_BODY(rename_to_replace, tc) 2569afb12baSDavid Bright { 2579afb12baSDavid Bright char expected_value; 2589afb12baSDavid Bright int fd; 2599afb12baSDavid Bright int fd2; 2609afb12baSDavid Bright 2619afb12baSDavid Bright // Some contents we can verify later 2629afb12baSDavid Bright expected_value = 'g'; 2639afb12baSDavid Bright 2649afb12baSDavid Bright gen_test_path(); 2659afb12baSDavid Bright fd = scribble_object(test_path, expected_value); 2669afb12baSDavid Bright close(fd); 2679afb12baSDavid Bright 2689afb12baSDavid Bright // Give the other some different value so we can detect success 2699afb12baSDavid Bright gen_test_path2(); 2709afb12baSDavid Bright fd2 = scribble_object(test_path2, 'h'); 2719afb12baSDavid Bright close(fd2); 2729afb12baSDavid Bright 2739afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0, 2749afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 2759afb12baSDavid Bright 2769afb12baSDavid Bright // Read back renamed; verify contents 2779afb12baSDavid Bright verify_object(test_path2, expected_value); 2789afb12baSDavid Bright } 2799afb12baSDavid Bright 2809afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_noreplace); 2819afb12baSDavid Bright ATF_TC_BODY(rename_to_noreplace, tc) 2829afb12baSDavid Bright { 2839afb12baSDavid Bright char expected_value_from; 2849afb12baSDavid Bright char expected_value_to; 2859afb12baSDavid Bright int fd_from; 2869afb12baSDavid Bright int fd_to; 2879afb12baSDavid Bright int rc; 2889afb12baSDavid Bright 2899afb12baSDavid Bright // Some contents we can verify later 2909afb12baSDavid Bright expected_value_from = 'g'; 2919afb12baSDavid Bright gen_test_path(); 2929afb12baSDavid Bright fd_from = scribble_object(test_path, expected_value_from); 2939afb12baSDavid Bright close(fd_from); 2949afb12baSDavid Bright 2959afb12baSDavid Bright // Give the other some different value so we can detect success 2969afb12baSDavid Bright expected_value_to = 'h'; 2979afb12baSDavid Bright gen_test_path2(); 2989afb12baSDavid Bright fd_to = scribble_object(test_path2, expected_value_to); 2999afb12baSDavid Bright close(fd_to); 3009afb12baSDavid Bright 3019afb12baSDavid Bright rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE); 3029afb12baSDavid Bright ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST), 3039afb12baSDavid Bright "shm_rename didn't fail as expected; errno: %d; return: %d", errno, 3049afb12baSDavid Bright rc); 3059afb12baSDavid Bright 3069afb12baSDavid Bright // Read back renamed; verify contents 3079afb12baSDavid Bright verify_object(test_path2, expected_value_to); 3089afb12baSDavid Bright } 3099afb12baSDavid Bright 3109afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange); 3119afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange, tc) 3129afb12baSDavid Bright { 3139afb12baSDavid Bright char expected_value_from; 3149afb12baSDavid Bright char expected_value_to; 3159afb12baSDavid Bright int fd_from; 3169afb12baSDavid Bright int fd_to; 3179afb12baSDavid Bright 3189afb12baSDavid Bright // Some contents we can verify later 3199afb12baSDavid Bright expected_value_from = 'g'; 3209afb12baSDavid Bright gen_test_path(); 3219afb12baSDavid Bright fd_from = scribble_object(test_path, expected_value_from); 3229afb12baSDavid Bright close(fd_from); 3239afb12baSDavid Bright 3249afb12baSDavid Bright // Give the other some different value so we can detect success 3259afb12baSDavid Bright expected_value_to = 'h'; 3269afb12baSDavid Bright gen_test_path2(); 3279afb12baSDavid Bright fd_to = scribble_object(test_path2, expected_value_to); 3289afb12baSDavid Bright close(fd_to); 3299afb12baSDavid Bright 3309afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 3319afb12baSDavid Bright SHM_RENAME_EXCHANGE) == 0, 3329afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 3339afb12baSDavid Bright 3349afb12baSDavid Bright // Read back renamed; verify contents 3359afb12baSDavid Bright verify_object(test_path, expected_value_to); 3369afb12baSDavid Bright verify_object(test_path2, expected_value_from); 3379afb12baSDavid Bright } 3389afb12baSDavid Bright 3399afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting); 3409afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange_nonexisting, tc) 3419afb12baSDavid Bright { 3429afb12baSDavid Bright char expected_value_from; 3439afb12baSDavid Bright int fd_from; 3449afb12baSDavid Bright 3459afb12baSDavid Bright // Some contents we can verify later 3469afb12baSDavid Bright expected_value_from = 'g'; 3479afb12baSDavid Bright gen_test_path(); 3489afb12baSDavid Bright fd_from = scribble_object(test_path, expected_value_from); 3499afb12baSDavid Bright close(fd_from); 3509afb12baSDavid Bright 3519afb12baSDavid Bright gen_test_path2(); 3529afb12baSDavid Bright 3539afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 3549afb12baSDavid Bright SHM_RENAME_EXCHANGE) == 0, 3559afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 3569afb12baSDavid Bright 3579afb12baSDavid Bright // Read back renamed; verify contents 3589afb12baSDavid Bright verify_object(test_path2, expected_value_from); 3599afb12baSDavid Bright } 3609afb12baSDavid Bright 3619afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_self); 3629afb12baSDavid Bright ATF_TC_BODY(rename_to_self, tc) 3639afb12baSDavid Bright { 3649afb12baSDavid Bright int fd; 3659afb12baSDavid Bright char expected_value; 3669afb12baSDavid Bright 3679afb12baSDavid Bright expected_value = 't'; 3689afb12baSDavid Bright 3699afb12baSDavid Bright gen_test_path(); 3709afb12baSDavid Bright fd = scribble_object(test_path, expected_value); 3719afb12baSDavid Bright close(fd); 3729afb12baSDavid Bright 3739afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0, 3749afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 3759afb12baSDavid Bright 3769afb12baSDavid Bright verify_object(test_path, expected_value); 3779afb12baSDavid Bright } 3789afb12baSDavid Bright 3799afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_flag); 3809afb12baSDavid Bright ATF_TC_BODY(rename_bad_flag, tc) 3819afb12baSDavid Bright { 3829afb12baSDavid Bright int fd; 3839afb12baSDavid Bright int rc; 3849afb12baSDavid Bright 3859afb12baSDavid Bright /* Make sure we don't fail out due to ENOENT */ 3869afb12baSDavid Bright gen_test_path(); 3879afb12baSDavid Bright gen_test_path2(); 3889afb12baSDavid Bright fd = scribble_object(test_path, 'd'); 3899afb12baSDavid Bright close(fd); 3909afb12baSDavid Bright fd = scribble_object(test_path2, 'd'); 3919afb12baSDavid Bright close(fd); 3929afb12baSDavid Bright 3939afb12baSDavid Bright /* 3949afb12baSDavid Bright * Note: if we end up with enough flags that we use all the bits, 3959afb12baSDavid Bright * then remove this test completely. 3969afb12baSDavid Bright */ 3979afb12baSDavid Bright rc = shm_rename(test_path, test_path2, INT_MIN); 3989afb12baSDavid Bright ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL), 3999afb12baSDavid Bright "shm_rename should have failed with EINVAL; got: return=%d, " 4009afb12baSDavid Bright "errno=%d", rc, errno); 4019afb12baSDavid Bright } 4029afb12baSDavid Bright 4034fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(reopen_object); 4044fdc3d75SEnji Cooper ATF_TC_BODY(reopen_object, tc) 4054fdc3d75SEnji Cooper { 4064fdc3d75SEnji Cooper char *page; 40794ebd6f5SEnji Cooper int fd, pagesize; 40894ebd6f5SEnji Cooper 40994ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 4104fdc3d75SEnji Cooper 4119afb12baSDavid Bright gen_test_path(); 4129afb12baSDavid Bright fd = scribble_object(test_path, '1'); 4134fdc3d75SEnji Cooper close(fd); 4144fdc3d75SEnji Cooper 4154fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY, 0777); 4164fdc3d75SEnji Cooper if (fd < 0) 4174fdc3d75SEnji Cooper atf_tc_fail("shm_open(2) failed; errno=%d", errno); 4184fdc3d75SEnji Cooper 41994ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 4204fdc3d75SEnji Cooper if (page == MAP_FAILED) 4214fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 4224fdc3d75SEnji Cooper 4234fdc3d75SEnji Cooper if (page[0] != '1') 4244fdc3d75SEnji Cooper atf_tc_fail("missing data ('%c' != '1')", page[0]); 4254fdc3d75SEnji Cooper 42694ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 42794ebd6f5SEnji Cooper errno); 4284fdc3d75SEnji Cooper close(fd); 4294fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 4304fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 4314fdc3d75SEnji Cooper } 4324fdc3d75SEnji Cooper 4334fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(readonly_mmap_write); 4344fdc3d75SEnji Cooper ATF_TC_BODY(readonly_mmap_write, tc) 4354fdc3d75SEnji Cooper { 4364fdc3d75SEnji Cooper char *page; 43794ebd6f5SEnji Cooper int fd, pagesize; 43894ebd6f5SEnji Cooper 43994ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 4404fdc3d75SEnji Cooper 4414fdc3d75SEnji Cooper gen_test_path(); 4424fdc3d75SEnji Cooper 4434fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 4444fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 4454fdc3d75SEnji Cooper 4464fdc3d75SEnji Cooper /* PROT_WRITE should fail with EACCES. */ 44794ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 4484fdc3d75SEnji Cooper if (page != MAP_FAILED) 4494fdc3d75SEnji Cooper atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly"); 4504fdc3d75SEnji Cooper 4514fdc3d75SEnji Cooper if (errno != EACCES) 4524fdc3d75SEnji Cooper atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; " 4534fdc3d75SEnji Cooper "errno=%d", errno); 4544fdc3d75SEnji Cooper 4554fdc3d75SEnji Cooper close(fd); 4564fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 4574fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 4584fdc3d75SEnji Cooper } 4594fdc3d75SEnji Cooper 4604fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_after_link); 4614fdc3d75SEnji Cooper ATF_TC_BODY(open_after_link, tc) 4624fdc3d75SEnji Cooper { 4634fdc3d75SEnji Cooper int fd; 4644fdc3d75SEnji Cooper 4654fdc3d75SEnji Cooper gen_test_path(); 4664fdc3d75SEnji Cooper 4674fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 4684fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 4694fdc3d75SEnji Cooper close(fd); 4704fdc3d75SEnji Cooper 4714fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d", 4724fdc3d75SEnji Cooper errno); 4734fdc3d75SEnji Cooper 4744fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT); 4754fdc3d75SEnji Cooper } 4764fdc3d75SEnji Cooper 4774fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_invalid_path); 4784fdc3d75SEnji Cooper ATF_TC_BODY(open_invalid_path, tc) 4794fdc3d75SEnji Cooper { 4804fdc3d75SEnji Cooper 4814fdc3d75SEnji Cooper shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL); 4824fdc3d75SEnji Cooper } 4834fdc3d75SEnji Cooper 4844fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_write_only); 4854fdc3d75SEnji Cooper ATF_TC_BODY(open_write_only, tc) 4864fdc3d75SEnji Cooper { 4874fdc3d75SEnji Cooper 4884fdc3d75SEnji Cooper gen_test_path(); 4894fdc3d75SEnji Cooper 4904fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL); 4914fdc3d75SEnji Cooper } 4924fdc3d75SEnji Cooper 4934fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_extra_flags); 4944fdc3d75SEnji Cooper ATF_TC_BODY(open_extra_flags, tc) 4954fdc3d75SEnji Cooper { 4964fdc3d75SEnji Cooper 4974fdc3d75SEnji Cooper gen_test_path(); 4984fdc3d75SEnji Cooper 4994fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL); 5004fdc3d75SEnji Cooper } 5014fdc3d75SEnji Cooper 5024fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon); 5034fdc3d75SEnji Cooper ATF_TC_BODY(open_anon, tc) 5044fdc3d75SEnji Cooper { 5054fdc3d75SEnji Cooper int fd; 5064fdc3d75SEnji Cooper 5074fdc3d75SEnji Cooper fd = shm_open(SHM_ANON, O_RDWR, 0777); 5084fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 5094fdc3d75SEnji Cooper close(fd); 5104fdc3d75SEnji Cooper } 5114fdc3d75SEnji Cooper 5124fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon_readonly); 5134fdc3d75SEnji Cooper ATF_TC_BODY(open_anon_readonly, tc) 5144fdc3d75SEnji Cooper { 5154fdc3d75SEnji Cooper 5164fdc3d75SEnji Cooper shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); 5174fdc3d75SEnji Cooper } 5184fdc3d75SEnji Cooper 5194fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_bad_path_pointer); 5204fdc3d75SEnji Cooper ATF_TC_BODY(open_bad_path_pointer, tc) 5214fdc3d75SEnji Cooper { 5224fdc3d75SEnji Cooper 5234fdc3d75SEnji Cooper shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT); 5244fdc3d75SEnji Cooper } 5254fdc3d75SEnji Cooper 5264fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_path_too_long); 5274fdc3d75SEnji Cooper ATF_TC_BODY(open_path_too_long, tc) 5284fdc3d75SEnji Cooper { 5294fdc3d75SEnji Cooper char *page; 5304fdc3d75SEnji Cooper 5314fdc3d75SEnji Cooper page = malloc(MAXPATHLEN + 1); 5324fdc3d75SEnji Cooper memset(page, 'a', MAXPATHLEN); 5334fdc3d75SEnji Cooper page[MAXPATHLEN] = '\0'; 5344fdc3d75SEnji Cooper shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG); 5354fdc3d75SEnji Cooper free(page); 5364fdc3d75SEnji Cooper } 5374fdc3d75SEnji Cooper 5384fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_nonexisting_object); 5394fdc3d75SEnji Cooper ATF_TC_BODY(open_nonexisting_object, tc) 5404fdc3d75SEnji Cooper { 5414fdc3d75SEnji Cooper 5424fdc3d75SEnji Cooper shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT); 5434fdc3d75SEnji Cooper } 5444fdc3d75SEnji Cooper 5454fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_create_existing_object); 5464fdc3d75SEnji Cooper ATF_TC_BODY(open_create_existing_object, tc) 5474fdc3d75SEnji Cooper { 5484fdc3d75SEnji Cooper int fd; 5494fdc3d75SEnji Cooper 5504fdc3d75SEnji Cooper gen_test_path(); 5514fdc3d75SEnji Cooper 5524fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777); 5534fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 5544fdc3d75SEnji Cooper close(fd); 5554fdc3d75SEnji Cooper 5564fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL, 5574fdc3d75SEnji Cooper 0777, EEXIST); 5584fdc3d75SEnji Cooper 5594fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 5604fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 5614fdc3d75SEnji Cooper } 5624fdc3d75SEnji Cooper 5634fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(trunc_resets_object); 5644fdc3d75SEnji Cooper ATF_TC_BODY(trunc_resets_object, tc) 5654fdc3d75SEnji Cooper { 5664fdc3d75SEnji Cooper struct stat sb; 5674fdc3d75SEnji Cooper int fd; 5684fdc3d75SEnji Cooper 5694fdc3d75SEnji Cooper gen_test_path(); 5704fdc3d75SEnji Cooper 5714fdc3d75SEnji Cooper /* Create object and set size to 1024. */ 5724fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDWR | O_CREAT, 0777); 5734fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 5744fdc3d75SEnji Cooper ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1, 5754fdc3d75SEnji Cooper "ftruncate failed; errno=%d", errno); 5764fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 5774fdc3d75SEnji Cooper "fstat(1) failed; errno=%d", errno); 5784fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size); 5794fdc3d75SEnji Cooper close(fd); 5804fdc3d75SEnji Cooper 5814fdc3d75SEnji Cooper /* Open with O_TRUNC which should reset size to 0. */ 5824fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777); 5834fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno); 5844fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 5854fdc3d75SEnji Cooper "fstat(2) failed; errno=%d", errno); 5864fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sb.st_size == 0, 5874fdc3d75SEnji Cooper "size was not 0 after truncation: %d", (int)sb.st_size); 5884fdc3d75SEnji Cooper close(fd); 5894fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 5904fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 5914fdc3d75SEnji Cooper } 5924fdc3d75SEnji Cooper 5934fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer); 5944fdc3d75SEnji Cooper ATF_TC_BODY(unlink_bad_path_pointer, tc) 5954fdc3d75SEnji Cooper { 5964fdc3d75SEnji Cooper 5974fdc3d75SEnji Cooper shm_unlink_should_fail((char *)1024, EFAULT); 5984fdc3d75SEnji Cooper } 5994fdc3d75SEnji Cooper 6004fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_path_too_long); 6014fdc3d75SEnji Cooper ATF_TC_BODY(unlink_path_too_long, tc) 6024fdc3d75SEnji Cooper { 6034fdc3d75SEnji Cooper char *page; 6044fdc3d75SEnji Cooper 6054fdc3d75SEnji Cooper page = malloc(MAXPATHLEN + 1); 6064fdc3d75SEnji Cooper memset(page, 'a', MAXPATHLEN); 6074fdc3d75SEnji Cooper page[MAXPATHLEN] = '\0'; 6084fdc3d75SEnji Cooper shm_unlink_should_fail(page, ENAMETOOLONG); 6094fdc3d75SEnji Cooper free(page); 6104fdc3d75SEnji Cooper } 6114fdc3d75SEnji Cooper 6124fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(object_resize); 6134fdc3d75SEnji Cooper ATF_TC_BODY(object_resize, tc) 6144fdc3d75SEnji Cooper { 6154fdc3d75SEnji Cooper pid_t pid; 6164fdc3d75SEnji Cooper struct stat sb; 61794ebd6f5SEnji Cooper char *page; 61894ebd6f5SEnji Cooper int fd, pagesize, status; 61994ebd6f5SEnji Cooper 62094ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 6214fdc3d75SEnji Cooper 6224fdc3d75SEnji Cooper /* Start off with a size of a single page. */ 6234fdc3d75SEnji Cooper fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777); 6244fdc3d75SEnji Cooper if (fd < 0) 6254fdc3d75SEnji Cooper atf_tc_fail("shm_open failed; errno=%d", errno); 6264fdc3d75SEnji Cooper 62794ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 6284fdc3d75SEnji Cooper atf_tc_fail("ftruncate(1) failed; errno=%d", errno); 6294fdc3d75SEnji Cooper 6304fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 6314fdc3d75SEnji Cooper atf_tc_fail("fstat(1) failed; errno=%d", errno); 6324fdc3d75SEnji Cooper 63394ebd6f5SEnji Cooper if (sb.st_size != pagesize) 6344fdc3d75SEnji Cooper atf_tc_fail("first resize failed (%d != %d)", 63594ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 6364fdc3d75SEnji Cooper 6374fdc3d75SEnji Cooper /* Write a '1' to the first byte. */ 63894ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 6394fdc3d75SEnji Cooper if (page == MAP_FAILED) 6404fdc3d75SEnji Cooper atf_tc_fail("mmap(1)"); 6414fdc3d75SEnji Cooper 6424fdc3d75SEnji Cooper page[0] = '1'; 6434fdc3d75SEnji Cooper 64494ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 64594ebd6f5SEnji Cooper errno); 6464fdc3d75SEnji Cooper 6474fdc3d75SEnji Cooper /* Grow the object to 2 pages. */ 64894ebd6f5SEnji Cooper if (ftruncate(fd, pagesize * 2) < 0) 6494fdc3d75SEnji Cooper atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 6504fdc3d75SEnji Cooper 6514fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 6524fdc3d75SEnji Cooper atf_tc_fail("fstat(2) failed; errno=%d", errno); 6534fdc3d75SEnji Cooper 65494ebd6f5SEnji Cooper if (sb.st_size != pagesize * 2) 6554fdc3d75SEnji Cooper atf_tc_fail("second resize failed (%d != %d)", 65694ebd6f5SEnji Cooper (int)sb.st_size, pagesize * 2); 6574fdc3d75SEnji Cooper 6584fdc3d75SEnji Cooper /* Check for '1' at the first byte. */ 65994ebd6f5SEnji Cooper page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 6604fdc3d75SEnji Cooper if (page == MAP_FAILED) 6614fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 6624fdc3d75SEnji Cooper 6634fdc3d75SEnji Cooper if (page[0] != '1') 6644fdc3d75SEnji Cooper atf_tc_fail("'%c' != '1'", page[0]); 6654fdc3d75SEnji Cooper 6664fdc3d75SEnji Cooper /* Write a '2' at the start of the second page. */ 66794ebd6f5SEnji Cooper page[pagesize] = '2'; 6684fdc3d75SEnji Cooper 6694fdc3d75SEnji Cooper /* Shrink the object back to 1 page. */ 67094ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 6714fdc3d75SEnji Cooper atf_tc_fail("ftruncate(3) failed; errno=%d", errno); 6724fdc3d75SEnji Cooper 6734fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 6744fdc3d75SEnji Cooper atf_tc_fail("fstat(3) failed; errno=%d", errno); 6754fdc3d75SEnji Cooper 67694ebd6f5SEnji Cooper if (sb.st_size != pagesize) 6774fdc3d75SEnji Cooper atf_tc_fail("third resize failed (%d != %d)", 67894ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 6794fdc3d75SEnji Cooper 6804fdc3d75SEnji Cooper /* 6814fdc3d75SEnji Cooper * Fork a child process to make sure the second page is no 6824fdc3d75SEnji Cooper * longer valid. 6834fdc3d75SEnji Cooper */ 6844fdc3d75SEnji Cooper pid = fork(); 6854fdc3d75SEnji Cooper if (pid == -1) 6864fdc3d75SEnji Cooper atf_tc_fail("fork failed; errno=%d", errno); 6874fdc3d75SEnji Cooper 6884fdc3d75SEnji Cooper if (pid == 0) { 6894fdc3d75SEnji Cooper struct rlimit lim; 6904fdc3d75SEnji Cooper char c; 6914fdc3d75SEnji Cooper 6924fdc3d75SEnji Cooper /* Don't generate a core dump. */ 69394ebd6f5SEnji Cooper ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0); 6944fdc3d75SEnji Cooper lim.rlim_cur = 0; 69594ebd6f5SEnji Cooper ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0); 6964fdc3d75SEnji Cooper 6974fdc3d75SEnji Cooper /* 6984fdc3d75SEnji Cooper * The previous ftruncate(2) shrunk the backing object 6994fdc3d75SEnji Cooper * so that this address is no longer valid, so reading 700*4f775512SJilles Tjoelker * from it should trigger a SIGBUS. 7014fdc3d75SEnji Cooper */ 70294ebd6f5SEnji Cooper c = page[pagesize]; 7034fdc3d75SEnji Cooper fprintf(stderr, "child: page 1: '%c'\n", c); 7044fdc3d75SEnji Cooper exit(0); 7054fdc3d75SEnji Cooper } 7064fdc3d75SEnji Cooper 7074fdc3d75SEnji Cooper if (wait(&status) < 0) 7084fdc3d75SEnji Cooper atf_tc_fail("wait failed; errno=%d", errno); 7094fdc3d75SEnji Cooper 710*4f775512SJilles Tjoelker if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS) 7114fdc3d75SEnji Cooper atf_tc_fail("child terminated with status %x", status); 7124fdc3d75SEnji Cooper 7134fdc3d75SEnji Cooper /* Grow the object back to 2 pages. */ 71494ebd6f5SEnji Cooper if (ftruncate(fd, pagesize * 2) < 0) 7154fdc3d75SEnji Cooper atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 7164fdc3d75SEnji Cooper 7174fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 7184fdc3d75SEnji Cooper atf_tc_fail("fstat(2) failed; errno=%d", errno); 7194fdc3d75SEnji Cooper 72094ebd6f5SEnji Cooper if (sb.st_size != pagesize * 2) 7214fdc3d75SEnji Cooper atf_tc_fail("fourth resize failed (%d != %d)", 72294ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 7234fdc3d75SEnji Cooper 7244fdc3d75SEnji Cooper /* 7254fdc3d75SEnji Cooper * Note that the mapping at 'page' for the second page is 7264fdc3d75SEnji Cooper * still valid, and now that the shm object has been grown 7274fdc3d75SEnji Cooper * back up to 2 pages, there is now memory backing this page 7284fdc3d75SEnji Cooper * so the read will work. However, the data should be zero 7294fdc3d75SEnji Cooper * rather than '2' as the old data was thrown away when the 7304fdc3d75SEnji Cooper * object was shrunk and the new pages when an object are 7314fdc3d75SEnji Cooper * grown are zero-filled. 7324fdc3d75SEnji Cooper */ 73394ebd6f5SEnji Cooper if (page[pagesize] != 0) 7344fdc3d75SEnji Cooper atf_tc_fail("invalid data at %d: %x != 0", 73594ebd6f5SEnji Cooper pagesize, (int)page[pagesize]); 7364fdc3d75SEnji Cooper 7374fdc3d75SEnji Cooper close(fd); 7384fdc3d75SEnji Cooper } 7394fdc3d75SEnji Cooper 7404fdc3d75SEnji Cooper /* Signal handler which does nothing. */ 7414fdc3d75SEnji Cooper static void 7424fdc3d75SEnji Cooper ignoreit(int sig __unused) 7434fdc3d75SEnji Cooper { 7444fdc3d75SEnji Cooper ; 7454fdc3d75SEnji Cooper } 7464fdc3d75SEnji Cooper 7474fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork); 7484fdc3d75SEnji Cooper ATF_TC_BODY(shm_functionality_across_fork, tc) 7494fdc3d75SEnji Cooper { 7504fdc3d75SEnji Cooper char *cp, c; 7514fdc3d75SEnji Cooper int error, desc, rv; 7524fdc3d75SEnji Cooper long scval; 7534fdc3d75SEnji Cooper sigset_t ss; 7544fdc3d75SEnji Cooper struct sigaction sa; 7554fdc3d75SEnji Cooper void *region; 7564fdc3d75SEnji Cooper size_t i, psize; 7574fdc3d75SEnji Cooper 7584fdc3d75SEnji Cooper #ifndef _POSIX_SHARED_MEMORY_OBJECTS 7594fdc3d75SEnji Cooper printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 7604fdc3d75SEnji Cooper #else 7614fdc3d75SEnji Cooper printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 7624fdc3d75SEnji Cooper (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 7634fdc3d75SEnji Cooper if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 7644fdc3d75SEnji Cooper printf("***Indicates this feature may be unsupported!\n"); 7654fdc3d75SEnji Cooper #endif 7664fdc3d75SEnji Cooper errno = 0; 7674fdc3d75SEnji Cooper scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 7684fdc3d75SEnji Cooper if (scval == -1 && errno != 0) { 7694fdc3d75SEnji Cooper atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; " 7704fdc3d75SEnji Cooper "errno=%d", errno); 7714fdc3d75SEnji Cooper } else { 7724fdc3d75SEnji Cooper printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 7734fdc3d75SEnji Cooper scval); 7744fdc3d75SEnji Cooper if (scval == -1) 7754fdc3d75SEnji Cooper printf("***Indicates this feature is unsupported!\n"); 7764fdc3d75SEnji Cooper } 7774fdc3d75SEnji Cooper 7784fdc3d75SEnji Cooper errno = 0; 7794fdc3d75SEnji Cooper scval = sysconf(_SC_PAGESIZE); 7804fdc3d75SEnji Cooper if (scval == -1 && errno != 0) { 7814fdc3d75SEnji Cooper atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno); 78294ebd6f5SEnji Cooper } else if (scval <= 0) { 7834fdc3d75SEnji Cooper fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld", 7844fdc3d75SEnji Cooper scval); 7854fdc3d75SEnji Cooper psize = 4096; 7864fdc3d75SEnji Cooper } else { 7874fdc3d75SEnji Cooper printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 7884fdc3d75SEnji Cooper psize = scval; 7894fdc3d75SEnji Cooper } 7904fdc3d75SEnji Cooper 7914fdc3d75SEnji Cooper gen_test_path(); 7924fdc3d75SEnji Cooper desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600); 7934fdc3d75SEnji Cooper 7944fdc3d75SEnji Cooper ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno); 7954fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 7964fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 7974fdc3d75SEnji Cooper ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1, 7984fdc3d75SEnji Cooper "ftruncate failed; errno=%d", errno); 7994fdc3d75SEnji Cooper 80094ebd6f5SEnji Cooper region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0); 8014fdc3d75SEnji Cooper ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno); 8024fdc3d75SEnji Cooper memset(region, '\377', psize); 8034fdc3d75SEnji Cooper 8044fdc3d75SEnji Cooper sa.sa_flags = 0; 8054fdc3d75SEnji Cooper sa.sa_handler = ignoreit; 8064fdc3d75SEnji Cooper sigemptyset(&sa.sa_mask); 8074fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0, 8084fdc3d75SEnji Cooper "sigaction failed; errno=%d", errno); 8094fdc3d75SEnji Cooper 8104fdc3d75SEnji Cooper sigemptyset(&ss); 8114fdc3d75SEnji Cooper sigaddset(&ss, SIGUSR1); 8124fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0, 8134fdc3d75SEnji Cooper "sigprocmask failed; errno=%d", errno); 8144fdc3d75SEnji Cooper 8154fdc3d75SEnji Cooper rv = fork(); 8164fdc3d75SEnji Cooper ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno); 8174fdc3d75SEnji Cooper if (rv == 0) { 8184fdc3d75SEnji Cooper sigemptyset(&ss); 8194fdc3d75SEnji Cooper sigsuspend(&ss); 8204fdc3d75SEnji Cooper 8214fdc3d75SEnji Cooper for (cp = region; cp < (char *)region + psize; cp++) { 8224fdc3d75SEnji Cooper if (*cp != '\151') 8234fdc3d75SEnji Cooper _exit(1); 8244fdc3d75SEnji Cooper } 8254fdc3d75SEnji Cooper if (lseek(desc, 0, SEEK_SET) == -1) 8264fdc3d75SEnji Cooper _exit(1); 8274fdc3d75SEnji Cooper for (i = 0; i < psize; i++) { 8284fdc3d75SEnji Cooper error = read(desc, &c, 1); 8294fdc3d75SEnji Cooper if (c != '\151') 8304fdc3d75SEnji Cooper _exit(1); 8314fdc3d75SEnji Cooper } 8324fdc3d75SEnji Cooper _exit(0); 8334fdc3d75SEnji Cooper } else { 8344fdc3d75SEnji Cooper int status; 8354fdc3d75SEnji Cooper 8364fdc3d75SEnji Cooper memset(region, '\151', psize - 2); 8374fdc3d75SEnji Cooper error = pwrite(desc, region, 2, psize - 2); 8384fdc3d75SEnji Cooper if (error != 2) { 8394fdc3d75SEnji Cooper if (error >= 0) 8404fdc3d75SEnji Cooper atf_tc_fail("short write; %d bytes written", 8414fdc3d75SEnji Cooper error); 8424fdc3d75SEnji Cooper else 8434fdc3d75SEnji Cooper atf_tc_fail("shmfd write"); 8444fdc3d75SEnji Cooper } 8454fdc3d75SEnji Cooper kill(rv, SIGUSR1); 8464fdc3d75SEnji Cooper waitpid(rv, &status, 0); 8474fdc3d75SEnji Cooper 8484fdc3d75SEnji Cooper if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 8494fdc3d75SEnji Cooper printf("Functionality test successful\n"); 8504fdc3d75SEnji Cooper } else if (WIFEXITED(status)) { 8514fdc3d75SEnji Cooper atf_tc_fail("Child process exited with status %d", 8524fdc3d75SEnji Cooper WEXITSTATUS(status)); 8534fdc3d75SEnji Cooper } else { 8544fdc3d75SEnji Cooper atf_tc_fail("Child process terminated with %s", 8554fdc3d75SEnji Cooper strsignal(WTERMSIG(status))); 8564fdc3d75SEnji Cooper } 8574fdc3d75SEnji Cooper } 85894ebd6f5SEnji Cooper 85994ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d", 86094ebd6f5SEnji Cooper errno); 86194ebd6f5SEnji Cooper shm_unlink(test_path); 8624fdc3d75SEnji Cooper } 8634fdc3d75SEnji Cooper 86495aa96f3SKyle Evans ATF_TC_WITHOUT_HEAD(cloexec); 86595aa96f3SKyle Evans ATF_TC_BODY(cloexec, tc) 86695aa96f3SKyle Evans { 86795aa96f3SKyle Evans int fd; 86895aa96f3SKyle Evans 86995aa96f3SKyle Evans gen_test_path(); 87095aa96f3SKyle Evans 87195aa96f3SKyle Evans /* shm_open(2) is required to set FD_CLOEXEC */ 87295aa96f3SKyle Evans fd = shm_open(SHM_ANON, O_RDWR, 0777); 87395aa96f3SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 87495aa96f3SKyle Evans ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0); 87595aa96f3SKyle Evans close(fd); 87695aa96f3SKyle Evans 87795aa96f3SKyle Evans /* Also make sure that named shm is correct */ 87895aa96f3SKyle Evans fd = shm_open(test_path, O_CREAT | O_RDWR, 0600); 87995aa96f3SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 88095aa96f3SKyle Evans ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0); 88195aa96f3SKyle Evans close(fd); 88295aa96f3SKyle Evans } 88395aa96f3SKyle Evans 88495aa96f3SKyle Evans 8854fdc3d75SEnji Cooper ATF_TP_ADD_TCS(tp) 8864fdc3d75SEnji Cooper { 8874fdc3d75SEnji Cooper 8884fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, remap_object); 8899afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_from_anon); 8909afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_bad_path_pointer); 8919afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_from_nonexisting); 8929afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_anon); 8939afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_replace); 8949afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_noreplace); 8959afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_exchange); 8969afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting); 8979afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_self); 8989afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_bad_flag); 8994fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, reopen_object); 9004fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, readonly_mmap_write); 9014fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_after_link); 9024fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_invalid_path); 9034fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_write_only); 9044fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_extra_flags); 9054fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_anon); 9064fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_anon_readonly); 9074fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_bad_path_pointer); 9084fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_path_too_long); 9094fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_nonexisting_object); 9104fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_create_existing_object); 9114fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 9124fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, trunc_resets_object); 9134fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 9144fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, unlink_path_too_long); 9154fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, object_resize); 91695aa96f3SKyle Evans ATF_TP_ADD_TC(tp, cloexec); 9174fdc3d75SEnji Cooper 9184fdc3d75SEnji Cooper return (atf_no_error()); 9194fdc3d75SEnji Cooper } 920