157718be8SEnji Cooper /* $NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper /*- 457718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc. 557718be8SEnji Cooper * All rights reserved. 657718be8SEnji Cooper * 757718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation 857718be8SEnji Cooper * by Jukka Ruohonen. 957718be8SEnji Cooper * 1057718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 1157718be8SEnji Cooper * modification, are permitted provided that the following conditions 1257718be8SEnji Cooper * are met: 1357718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 1457718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 1557718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 1657718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 1757718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 1857718be8SEnji Cooper * 1957718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2057718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2157718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2257718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2357718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2457718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2557718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2657718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2757718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2857718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2957718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 3057718be8SEnji Cooper */ 3157718be8SEnji Cooper 3257718be8SEnji Cooper /*- 3357718be8SEnji Cooper * Copyright (c)2004 YAMAMOTO Takashi, 3457718be8SEnji Cooper * All rights reserved. 3557718be8SEnji Cooper * 3657718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 3757718be8SEnji Cooper * modification, are permitted provided that the following conditions 3857718be8SEnji Cooper * are met: 3957718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 4057718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 4157718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 4257718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 4357718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 4457718be8SEnji Cooper * 4557718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4657718be8SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4757718be8SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4857718be8SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4957718be8SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5057718be8SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5157718be8SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5257718be8SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5357718be8SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5457718be8SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5557718be8SEnji Cooper * SUCH DAMAGE. 5657718be8SEnji Cooper */ 5757718be8SEnji Cooper #include <sys/cdefs.h> 5857718be8SEnji Cooper __RCSID("$NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $"); 5957718be8SEnji Cooper 6057718be8SEnji Cooper #include <sys/param.h> 6157718be8SEnji Cooper #include <sys/mman.h> 6257718be8SEnji Cooper #include <sys/socket.h> 6357718be8SEnji Cooper #include <sys/sysctl.h> 6457718be8SEnji Cooper #include <sys/wait.h> 6557718be8SEnji Cooper 6657718be8SEnji Cooper #include <atf-c.h> 6757718be8SEnji Cooper #include <errno.h> 6857718be8SEnji Cooper #include <fcntl.h> 6957718be8SEnji Cooper #include <signal.h> 7057718be8SEnji Cooper #include <stdio.h> 7157718be8SEnji Cooper #include <stdlib.h> 7257718be8SEnji Cooper #include <string.h> 7357718be8SEnji Cooper #include <unistd.h> 7457718be8SEnji Cooper #include <paths.h> 75*41acfd75SEnji Cooper #ifdef __NetBSD__ 7657718be8SEnji Cooper #include <machine/disklabel.h> 77*41acfd75SEnji Cooper #endif 78*41acfd75SEnji Cooper 79*41acfd75SEnji Cooper #ifdef __FreeBSD__ 80*41acfd75SEnji Cooper #include <sys/disklabel.h> 81*41acfd75SEnji Cooper #include <sys/stat.h> 82*41acfd75SEnji Cooper #include <stdint.h> 83*41acfd75SEnji Cooper #endif 8457718be8SEnji Cooper 8557718be8SEnji Cooper static long page = 0; 8657718be8SEnji Cooper static char path[] = "mmap"; 8757718be8SEnji Cooper static void map_check(void *, int); 8857718be8SEnji Cooper static void map_sighandler(int); 8957718be8SEnji Cooper static void testloan(void *, void *, char, int); 9057718be8SEnji Cooper 9157718be8SEnji Cooper #define BUFSIZE (32 * 1024) /* enough size to trigger sosend_loan */ 9257718be8SEnji Cooper 9357718be8SEnji Cooper static void 9457718be8SEnji Cooper map_check(void *map, int flag) 9557718be8SEnji Cooper { 9657718be8SEnji Cooper 9757718be8SEnji Cooper if (flag != 0) { 9857718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 9957718be8SEnji Cooper return; 10057718be8SEnji Cooper } 10157718be8SEnji Cooper 10257718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 10357718be8SEnji Cooper ATF_REQUIRE(munmap(map, page) == 0); 10457718be8SEnji Cooper } 10557718be8SEnji Cooper 10657718be8SEnji Cooper void 10757718be8SEnji Cooper testloan(void *vp, void *vp2, char pat, int docheck) 10857718be8SEnji Cooper { 10957718be8SEnji Cooper char buf[BUFSIZE]; 11057718be8SEnji Cooper char backup[BUFSIZE]; 11157718be8SEnji Cooper ssize_t nwritten; 11257718be8SEnji Cooper ssize_t nread; 11357718be8SEnji Cooper int fds[2]; 11457718be8SEnji Cooper int val; 11557718be8SEnji Cooper 11657718be8SEnji Cooper val = BUFSIZE; 11757718be8SEnji Cooper 11857718be8SEnji Cooper if (docheck != 0) 11957718be8SEnji Cooper (void)memcpy(backup, vp, BUFSIZE); 12057718be8SEnji Cooper 12157718be8SEnji Cooper if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds) != 0) 12257718be8SEnji Cooper atf_tc_fail("socketpair() failed"); 12357718be8SEnji Cooper 12457718be8SEnji Cooper val = BUFSIZE; 12557718be8SEnji Cooper 12657718be8SEnji Cooper if (setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0) 12757718be8SEnji Cooper atf_tc_fail("setsockopt() failed, SO_RCVBUF"); 12857718be8SEnji Cooper 12957718be8SEnji Cooper val = BUFSIZE; 13057718be8SEnji Cooper 13157718be8SEnji Cooper if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0) 13257718be8SEnji Cooper atf_tc_fail("setsockopt() failed, SO_SNDBUF"); 13357718be8SEnji Cooper 13457718be8SEnji Cooper if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != 0) 13557718be8SEnji Cooper atf_tc_fail("fcntl() failed"); 13657718be8SEnji Cooper 13757718be8SEnji Cooper nwritten = write(fds[0], (char *)vp + page, BUFSIZE - page); 13857718be8SEnji Cooper 13957718be8SEnji Cooper if (nwritten == -1) 14057718be8SEnji Cooper atf_tc_fail("write() failed"); 14157718be8SEnji Cooper 14257718be8SEnji Cooper /* Break loan. */ 14357718be8SEnji Cooper (void)memset(vp2, pat, BUFSIZE); 14457718be8SEnji Cooper 14557718be8SEnji Cooper nread = read(fds[1], buf + page, BUFSIZE - page); 14657718be8SEnji Cooper 14757718be8SEnji Cooper if (nread == -1) 14857718be8SEnji Cooper atf_tc_fail("read() failed"); 14957718be8SEnji Cooper 15057718be8SEnji Cooper if (nread != nwritten) 15157718be8SEnji Cooper atf_tc_fail("too short read"); 15257718be8SEnji Cooper 15357718be8SEnji Cooper if (docheck != 0 && memcmp(backup, buf + page, nread) != 0) 15457718be8SEnji Cooper atf_tc_fail("data mismatch"); 15557718be8SEnji Cooper 15657718be8SEnji Cooper ATF_REQUIRE(close(fds[0]) == 0); 15757718be8SEnji Cooper ATF_REQUIRE(close(fds[1]) == 0); 15857718be8SEnji Cooper } 15957718be8SEnji Cooper 16057718be8SEnji Cooper static void 16157718be8SEnji Cooper map_sighandler(int signo) 16257718be8SEnji Cooper { 16357718be8SEnji Cooper _exit(signo); 16457718be8SEnji Cooper } 16557718be8SEnji Cooper 166*41acfd75SEnji Cooper #ifdef __NetBSD__ 16757718be8SEnji Cooper ATF_TC(mmap_block); 16857718be8SEnji Cooper ATF_TC_HEAD(mmap_block, tc) 16957718be8SEnji Cooper { 17057718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) with a block device"); 17157718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 17257718be8SEnji Cooper } 17357718be8SEnji Cooper 17457718be8SEnji Cooper ATF_TC_BODY(mmap_block, tc) 17557718be8SEnji Cooper { 17657718be8SEnji Cooper static const int mib[] = { CTL_HW, HW_DISKNAMES }; 17757718be8SEnji Cooper static const unsigned int miblen = __arraycount(mib); 17857718be8SEnji Cooper char *map, *dk, *drives, dev[PATH_MAX]; 17957718be8SEnji Cooper size_t len; 18057718be8SEnji Cooper int fd = -1; 18157718be8SEnji Cooper 18257718be8SEnji Cooper atf_tc_skip("The test case causes a panic (PR kern/38889, kern/46592)"); 18357718be8SEnji Cooper 18457718be8SEnji Cooper ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0); 18557718be8SEnji Cooper drives = malloc(len); 18657718be8SEnji Cooper ATF_REQUIRE(drives != NULL); 18757718be8SEnji Cooper ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0); 18857718be8SEnji Cooper for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) { 18957718be8SEnji Cooper sprintf(dev, _PATH_DEV "%s%c", dk, 'a'+RAW_PART); 19057718be8SEnji Cooper fprintf(stderr, "trying: %s\n", dev); 19157718be8SEnji Cooper 19257718be8SEnji Cooper if ((fd = open(dev, O_RDONLY)) >= 0) { 19357718be8SEnji Cooper (void)fprintf(stderr, "using %s\n", dev); 19457718be8SEnji Cooper break; 19557718be8SEnji Cooper } 19657718be8SEnji Cooper } 19757718be8SEnji Cooper free(drives); 19857718be8SEnji Cooper 19957718be8SEnji Cooper if (fd < 0) 20057718be8SEnji Cooper atf_tc_skip("failed to find suitable block device"); 20157718be8SEnji Cooper 20257718be8SEnji Cooper map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0); 20357718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 20457718be8SEnji Cooper 20557718be8SEnji Cooper (void)fprintf(stderr, "first byte %x\n", *map); 20657718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 20757718be8SEnji Cooper (void)fprintf(stderr, "first byte %x\n", *map); 20857718be8SEnji Cooper 20957718be8SEnji Cooper ATF_REQUIRE(munmap(map, 4096) == 0); 21057718be8SEnji Cooper } 211*41acfd75SEnji Cooper #endif 21257718be8SEnji Cooper 21357718be8SEnji Cooper ATF_TC(mmap_err); 21457718be8SEnji Cooper ATF_TC_HEAD(mmap_err, tc) 21557718be8SEnji Cooper { 21657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)"); 21757718be8SEnji Cooper } 21857718be8SEnji Cooper 21957718be8SEnji Cooper ATF_TC_BODY(mmap_err, tc) 22057718be8SEnji Cooper { 22157718be8SEnji Cooper size_t addr = SIZE_MAX; 22257718be8SEnji Cooper void *map; 22357718be8SEnji Cooper 22457718be8SEnji Cooper errno = 0; 22557718be8SEnji Cooper map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0); 22657718be8SEnji Cooper 22757718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 22857718be8SEnji Cooper ATF_REQUIRE(errno == EBADF); 22957718be8SEnji Cooper 23057718be8SEnji Cooper errno = 0; 23157718be8SEnji Cooper map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0); 23257718be8SEnji Cooper 23357718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 23457718be8SEnji Cooper ATF_REQUIRE(errno == EINVAL); 23557718be8SEnji Cooper 23657718be8SEnji Cooper errno = 0; 23757718be8SEnji Cooper map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0); 23857718be8SEnji Cooper 23957718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 24057718be8SEnji Cooper ATF_REQUIRE(errno == EINVAL); 24157718be8SEnji Cooper } 24257718be8SEnji Cooper 24357718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_loan); 24457718be8SEnji Cooper ATF_TC_HEAD(mmap_loan, tc) 24557718be8SEnji Cooper { 24657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)"); 24757718be8SEnji Cooper } 24857718be8SEnji Cooper 24957718be8SEnji Cooper ATF_TC_BODY(mmap_loan, tc) 25057718be8SEnji Cooper { 25157718be8SEnji Cooper char buf[BUFSIZE]; 25257718be8SEnji Cooper char *vp, *vp2; 25357718be8SEnji Cooper int fd; 25457718be8SEnji Cooper 25557718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0600); 25657718be8SEnji Cooper ATF_REQUIRE(fd >= 0); 25757718be8SEnji Cooper 25857718be8SEnji Cooper (void)memset(buf, 'x', sizeof(buf)); 25957718be8SEnji Cooper (void)write(fd, buf, sizeof(buf)); 26057718be8SEnji Cooper 26157718be8SEnji Cooper vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 26257718be8SEnji Cooper MAP_FILE | MAP_PRIVATE, fd, 0); 26357718be8SEnji Cooper 26457718be8SEnji Cooper ATF_REQUIRE(vp != MAP_FAILED); 26557718be8SEnji Cooper 26657718be8SEnji Cooper vp2 = vp; 26757718be8SEnji Cooper 26857718be8SEnji Cooper testloan(vp, vp2, 'A', 0); 26957718be8SEnji Cooper testloan(vp, vp2, 'B', 1); 27057718be8SEnji Cooper 27157718be8SEnji Cooper ATF_REQUIRE(munmap(vp, BUFSIZE) == 0); 27257718be8SEnji Cooper 27357718be8SEnji Cooper vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 27457718be8SEnji Cooper MAP_FILE | MAP_SHARED, fd, 0); 27557718be8SEnji Cooper 27657718be8SEnji Cooper vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 27757718be8SEnji Cooper MAP_FILE | MAP_SHARED, fd, 0); 27857718be8SEnji Cooper 27957718be8SEnji Cooper ATF_REQUIRE(vp != MAP_FAILED); 28057718be8SEnji Cooper ATF_REQUIRE(vp2 != MAP_FAILED); 28157718be8SEnji Cooper 28257718be8SEnji Cooper testloan(vp, vp2, 'E', 1); 28357718be8SEnji Cooper 28457718be8SEnji Cooper ATF_REQUIRE(munmap(vp, BUFSIZE) == 0); 28557718be8SEnji Cooper ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0); 28657718be8SEnji Cooper } 28757718be8SEnji Cooper 28857718be8SEnji Cooper ATF_TC_CLEANUP(mmap_loan, tc) 28957718be8SEnji Cooper { 29057718be8SEnji Cooper (void)unlink(path); 29157718be8SEnji Cooper } 29257718be8SEnji Cooper 29357718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_prot_1); 29457718be8SEnji Cooper ATF_TC_HEAD(mmap_prot_1, tc) 29557718be8SEnji Cooper { 29657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1"); 29757718be8SEnji Cooper } 29857718be8SEnji Cooper 29957718be8SEnji Cooper ATF_TC_BODY(mmap_prot_1, tc) 30057718be8SEnji Cooper { 30157718be8SEnji Cooper void *map; 30257718be8SEnji Cooper int fd; 30357718be8SEnji Cooper 30457718be8SEnji Cooper /* 30557718be8SEnji Cooper * Open a file write-only and try to 30657718be8SEnji Cooper * map it read-only. This should fail. 30757718be8SEnji Cooper */ 30857718be8SEnji Cooper fd = open(path, O_WRONLY | O_CREAT, 0700); 30957718be8SEnji Cooper 31057718be8SEnji Cooper if (fd < 0) 31157718be8SEnji Cooper return; 31257718be8SEnji Cooper 31357718be8SEnji Cooper ATF_REQUIRE(write(fd, "XXX", 3) == 3); 31457718be8SEnji Cooper 31557718be8SEnji Cooper map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0); 31657718be8SEnji Cooper map_check(map, 1); 31757718be8SEnji Cooper 31857718be8SEnji Cooper map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); 31957718be8SEnji Cooper map_check(map, 0); 32057718be8SEnji Cooper 32157718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 32257718be8SEnji Cooper } 32357718be8SEnji Cooper 32457718be8SEnji Cooper ATF_TC_CLEANUP(mmap_prot_1, tc) 32557718be8SEnji Cooper { 32657718be8SEnji Cooper (void)unlink(path); 32757718be8SEnji Cooper } 32857718be8SEnji Cooper 32957718be8SEnji Cooper ATF_TC(mmap_prot_2); 33057718be8SEnji Cooper ATF_TC_HEAD(mmap_prot_2, tc) 33157718be8SEnji Cooper { 33257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2"); 33357718be8SEnji Cooper } 33457718be8SEnji Cooper 33557718be8SEnji Cooper ATF_TC_BODY(mmap_prot_2, tc) 33657718be8SEnji Cooper { 33757718be8SEnji Cooper char buf[2]; 33857718be8SEnji Cooper void *map; 33957718be8SEnji Cooper pid_t pid; 34057718be8SEnji Cooper int sta; 34157718be8SEnji Cooper 34257718be8SEnji Cooper /* 34357718be8SEnji Cooper * Make a PROT_NONE mapping and try to access it. 34457718be8SEnji Cooper * If we catch a SIGSEGV, all works as expected. 34557718be8SEnji Cooper */ 34657718be8SEnji Cooper map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 34757718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 34857718be8SEnji Cooper 34957718be8SEnji Cooper pid = fork(); 35057718be8SEnji Cooper ATF_REQUIRE(pid >= 0); 35157718be8SEnji Cooper 35257718be8SEnji Cooper if (pid == 0) { 35357718be8SEnji Cooper ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR); 35457718be8SEnji Cooper ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0); 35557718be8SEnji Cooper } 35657718be8SEnji Cooper 35757718be8SEnji Cooper (void)wait(&sta); 35857718be8SEnji Cooper 35957718be8SEnji Cooper ATF_REQUIRE(WIFEXITED(sta) != 0); 36057718be8SEnji Cooper ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV); 36157718be8SEnji Cooper ATF_REQUIRE(munmap(map, page) == 0); 36257718be8SEnji Cooper } 36357718be8SEnji Cooper 36457718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_prot_3); 36557718be8SEnji Cooper ATF_TC_HEAD(mmap_prot_3, tc) 36657718be8SEnji Cooper { 36757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3"); 36857718be8SEnji Cooper } 36957718be8SEnji Cooper 37057718be8SEnji Cooper ATF_TC_BODY(mmap_prot_3, tc) 37157718be8SEnji Cooper { 37257718be8SEnji Cooper char buf[2]; 37357718be8SEnji Cooper int fd, sta; 37457718be8SEnji Cooper void *map; 37557718be8SEnji Cooper pid_t pid; 37657718be8SEnji Cooper 37757718be8SEnji Cooper /* 37857718be8SEnji Cooper * Open a file, change the permissions 37957718be8SEnji Cooper * to read-only, and try to map it as 38057718be8SEnji Cooper * PROT_NONE. This should succeed, but 38157718be8SEnji Cooper * the access should generate SIGSEGV. 38257718be8SEnji Cooper */ 38357718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0700); 38457718be8SEnji Cooper 38557718be8SEnji Cooper if (fd < 0) 38657718be8SEnji Cooper return; 38757718be8SEnji Cooper 38857718be8SEnji Cooper ATF_REQUIRE(write(fd, "XXX", 3) == 3); 38957718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 39057718be8SEnji Cooper ATF_REQUIRE(chmod(path, 0444) == 0); 39157718be8SEnji Cooper 39257718be8SEnji Cooper fd = open(path, O_RDONLY); 39357718be8SEnji Cooper ATF_REQUIRE(fd != -1); 39457718be8SEnji Cooper 39557718be8SEnji Cooper map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0); 39657718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 39757718be8SEnji Cooper 39857718be8SEnji Cooper pid = fork(); 39957718be8SEnji Cooper 40057718be8SEnji Cooper ATF_REQUIRE(pid >= 0); 40157718be8SEnji Cooper 40257718be8SEnji Cooper if (pid == 0) { 40357718be8SEnji Cooper ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR); 40457718be8SEnji Cooper ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0); 40557718be8SEnji Cooper } 40657718be8SEnji Cooper 40757718be8SEnji Cooper (void)wait(&sta); 40857718be8SEnji Cooper 40957718be8SEnji Cooper ATF_REQUIRE(WIFEXITED(sta) != 0); 41057718be8SEnji Cooper ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV); 41157718be8SEnji Cooper ATF_REQUIRE(munmap(map, 3) == 0); 41257718be8SEnji Cooper } 41357718be8SEnji Cooper 41457718be8SEnji Cooper ATF_TC_CLEANUP(mmap_prot_3, tc) 41557718be8SEnji Cooper { 41657718be8SEnji Cooper (void)unlink(path); 41757718be8SEnji Cooper } 41857718be8SEnji Cooper 41957718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_truncate); 42057718be8SEnji Cooper ATF_TC_HEAD(mmap_truncate, tc) 42157718be8SEnji Cooper { 42257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)"); 42357718be8SEnji Cooper } 42457718be8SEnji Cooper 42557718be8SEnji Cooper ATF_TC_BODY(mmap_truncate, tc) 42657718be8SEnji Cooper { 42757718be8SEnji Cooper char *map; 42857718be8SEnji Cooper long i; 42957718be8SEnji Cooper int fd; 43057718be8SEnji Cooper 43157718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0700); 43257718be8SEnji Cooper 43357718be8SEnji Cooper if (fd < 0) 43457718be8SEnji Cooper return; 43557718be8SEnji Cooper 43657718be8SEnji Cooper /* 43757718be8SEnji Cooper * See that ftruncate(2) works 43857718be8SEnji Cooper * while the file is mapped. 43957718be8SEnji Cooper */ 44057718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page) == 0); 44157718be8SEnji Cooper 44257718be8SEnji Cooper map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE, 44357718be8SEnji Cooper fd, 0); 44457718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 44557718be8SEnji Cooper 44657718be8SEnji Cooper for (i = 0; i < page; i++) 44757718be8SEnji Cooper map[i] = 'x'; 44857718be8SEnji Cooper 44957718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, 0) == 0); 45057718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 8) == 0); 45157718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 4) == 0); 45257718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 2) == 0); 45357718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 12) == 0); 45457718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 64) == 0); 45557718be8SEnji Cooper 45657718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 45757718be8SEnji Cooper } 45857718be8SEnji Cooper 45957718be8SEnji Cooper ATF_TC_CLEANUP(mmap_truncate, tc) 46057718be8SEnji Cooper { 46157718be8SEnji Cooper (void)unlink(path); 46257718be8SEnji Cooper } 46357718be8SEnji Cooper 46457718be8SEnji Cooper ATF_TC(mmap_va0); 46557718be8SEnji Cooper ATF_TC_HEAD(mmap_va0, tc) 46657718be8SEnji Cooper { 46757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable"); 46857718be8SEnji Cooper } 46957718be8SEnji Cooper 47057718be8SEnji Cooper ATF_TC_BODY(mmap_va0, tc) 47157718be8SEnji Cooper { 47257718be8SEnji Cooper int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE; 47357718be8SEnji Cooper size_t len = sizeof(int); 47457718be8SEnji Cooper void *map; 47557718be8SEnji Cooper int val; 47657718be8SEnji Cooper 47757718be8SEnji Cooper /* 47857718be8SEnji Cooper * Make an anonymous fixed mapping at zero address. If the address 47957718be8SEnji Cooper * is restricted as noted in security(7), the syscall should fail. 48057718be8SEnji Cooper */ 481*41acfd75SEnji Cooper #ifdef __FreeBSD__ 482*41acfd75SEnji Cooper if (sysctlbyname("security.bsd.map_at_zero", &val, &len, NULL, 0) != 0) 483*41acfd75SEnji Cooper atf_tc_fail("failed to read security.bsd.map_at_zero"); 484*41acfd75SEnji Cooper val = !val; /* 1 == enable map at zero */ 485*41acfd75SEnji Cooper #endif 486*41acfd75SEnji Cooper #ifdef __NetBSD__ 48757718be8SEnji Cooper if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0) 48857718be8SEnji Cooper atf_tc_fail("failed to read vm.user_va0_disable"); 489*41acfd75SEnji Cooper #endif 49057718be8SEnji Cooper 49157718be8SEnji Cooper map = mmap(NULL, page, PROT_EXEC, flags, -1, 0); 49257718be8SEnji Cooper map_check(map, val); 49357718be8SEnji Cooper 49457718be8SEnji Cooper map = mmap(NULL, page, PROT_READ, flags, -1, 0); 49557718be8SEnji Cooper map_check(map, val); 49657718be8SEnji Cooper 49757718be8SEnji Cooper map = mmap(NULL, page, PROT_WRITE, flags, -1, 0); 49857718be8SEnji Cooper map_check(map, val); 49957718be8SEnji Cooper 50057718be8SEnji Cooper map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0); 50157718be8SEnji Cooper map_check(map, val); 50257718be8SEnji Cooper 50357718be8SEnji Cooper map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0); 50457718be8SEnji Cooper map_check(map, val); 50557718be8SEnji Cooper } 50657718be8SEnji Cooper 50757718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 50857718be8SEnji Cooper { 50957718be8SEnji Cooper page = sysconf(_SC_PAGESIZE); 51057718be8SEnji Cooper ATF_REQUIRE(page >= 0); 51157718be8SEnji Cooper 512*41acfd75SEnji Cooper #ifdef __NetBSD__ 51357718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_block); 514*41acfd75SEnji Cooper #endif 51557718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_err); 51657718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_loan); 51757718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_prot_1); 51857718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_prot_2); 51957718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_prot_3); 52057718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_truncate); 52157718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_va0); 52257718be8SEnji Cooper 52357718be8SEnji Cooper return atf_no_error(); 52457718be8SEnji Cooper } 525