1*57718be8SEnji Cooper /* $NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation 8*57718be8SEnji Cooper * by Jukka Ruohonen. 9*57718be8SEnji Cooper * 10*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 11*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 12*57718be8SEnji Cooper * are met: 13*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 14*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 15*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 16*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 17*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 18*57718be8SEnji Cooper * 19*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 30*57718be8SEnji Cooper */ 31*57718be8SEnji Cooper 32*57718be8SEnji Cooper /*- 33*57718be8SEnji Cooper * Copyright (c)2004 YAMAMOTO Takashi, 34*57718be8SEnji Cooper * All rights reserved. 35*57718be8SEnji Cooper * 36*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 37*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 38*57718be8SEnji Cooper * are met: 39*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 40*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 41*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 42*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 43*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 44*57718be8SEnji Cooper * 45*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46*57718be8SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47*57718be8SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48*57718be8SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49*57718be8SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50*57718be8SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51*57718be8SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52*57718be8SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53*57718be8SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54*57718be8SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55*57718be8SEnji Cooper * SUCH DAMAGE. 56*57718be8SEnji Cooper */ 57*57718be8SEnji Cooper #include <sys/cdefs.h> 58*57718be8SEnji Cooper __RCSID("$NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $"); 59*57718be8SEnji Cooper 60*57718be8SEnji Cooper #include <sys/param.h> 61*57718be8SEnji Cooper #include <sys/mman.h> 62*57718be8SEnji Cooper #include <sys/socket.h> 63*57718be8SEnji Cooper #include <sys/sysctl.h> 64*57718be8SEnji Cooper #include <sys/wait.h> 65*57718be8SEnji Cooper 66*57718be8SEnji Cooper #include <atf-c.h> 67*57718be8SEnji Cooper #include <errno.h> 68*57718be8SEnji Cooper #include <fcntl.h> 69*57718be8SEnji Cooper #include <signal.h> 70*57718be8SEnji Cooper #include <stdio.h> 71*57718be8SEnji Cooper #include <stdlib.h> 72*57718be8SEnji Cooper #include <string.h> 73*57718be8SEnji Cooper #include <unistd.h> 74*57718be8SEnji Cooper #include <paths.h> 75*57718be8SEnji Cooper #include <machine/disklabel.h> 76*57718be8SEnji Cooper 77*57718be8SEnji Cooper static long page = 0; 78*57718be8SEnji Cooper static char path[] = "mmap"; 79*57718be8SEnji Cooper static void map_check(void *, int); 80*57718be8SEnji Cooper static void map_sighandler(int); 81*57718be8SEnji Cooper static void testloan(void *, void *, char, int); 82*57718be8SEnji Cooper 83*57718be8SEnji Cooper #define BUFSIZE (32 * 1024) /* enough size to trigger sosend_loan */ 84*57718be8SEnji Cooper 85*57718be8SEnji Cooper static void 86*57718be8SEnji Cooper map_check(void *map, int flag) 87*57718be8SEnji Cooper { 88*57718be8SEnji Cooper 89*57718be8SEnji Cooper if (flag != 0) { 90*57718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 91*57718be8SEnji Cooper return; 92*57718be8SEnji Cooper } 93*57718be8SEnji Cooper 94*57718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 95*57718be8SEnji Cooper ATF_REQUIRE(munmap(map, page) == 0); 96*57718be8SEnji Cooper } 97*57718be8SEnji Cooper 98*57718be8SEnji Cooper void 99*57718be8SEnji Cooper testloan(void *vp, void *vp2, char pat, int docheck) 100*57718be8SEnji Cooper { 101*57718be8SEnji Cooper char buf[BUFSIZE]; 102*57718be8SEnji Cooper char backup[BUFSIZE]; 103*57718be8SEnji Cooper ssize_t nwritten; 104*57718be8SEnji Cooper ssize_t nread; 105*57718be8SEnji Cooper int fds[2]; 106*57718be8SEnji Cooper int val; 107*57718be8SEnji Cooper 108*57718be8SEnji Cooper val = BUFSIZE; 109*57718be8SEnji Cooper 110*57718be8SEnji Cooper if (docheck != 0) 111*57718be8SEnji Cooper (void)memcpy(backup, vp, BUFSIZE); 112*57718be8SEnji Cooper 113*57718be8SEnji Cooper if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds) != 0) 114*57718be8SEnji Cooper atf_tc_fail("socketpair() failed"); 115*57718be8SEnji Cooper 116*57718be8SEnji Cooper val = BUFSIZE; 117*57718be8SEnji Cooper 118*57718be8SEnji Cooper if (setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0) 119*57718be8SEnji Cooper atf_tc_fail("setsockopt() failed, SO_RCVBUF"); 120*57718be8SEnji Cooper 121*57718be8SEnji Cooper val = BUFSIZE; 122*57718be8SEnji Cooper 123*57718be8SEnji Cooper if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0) 124*57718be8SEnji Cooper atf_tc_fail("setsockopt() failed, SO_SNDBUF"); 125*57718be8SEnji Cooper 126*57718be8SEnji Cooper if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != 0) 127*57718be8SEnji Cooper atf_tc_fail("fcntl() failed"); 128*57718be8SEnji Cooper 129*57718be8SEnji Cooper nwritten = write(fds[0], (char *)vp + page, BUFSIZE - page); 130*57718be8SEnji Cooper 131*57718be8SEnji Cooper if (nwritten == -1) 132*57718be8SEnji Cooper atf_tc_fail("write() failed"); 133*57718be8SEnji Cooper 134*57718be8SEnji Cooper /* Break loan. */ 135*57718be8SEnji Cooper (void)memset(vp2, pat, BUFSIZE); 136*57718be8SEnji Cooper 137*57718be8SEnji Cooper nread = read(fds[1], buf + page, BUFSIZE - page); 138*57718be8SEnji Cooper 139*57718be8SEnji Cooper if (nread == -1) 140*57718be8SEnji Cooper atf_tc_fail("read() failed"); 141*57718be8SEnji Cooper 142*57718be8SEnji Cooper if (nread != nwritten) 143*57718be8SEnji Cooper atf_tc_fail("too short read"); 144*57718be8SEnji Cooper 145*57718be8SEnji Cooper if (docheck != 0 && memcmp(backup, buf + page, nread) != 0) 146*57718be8SEnji Cooper atf_tc_fail("data mismatch"); 147*57718be8SEnji Cooper 148*57718be8SEnji Cooper ATF_REQUIRE(close(fds[0]) == 0); 149*57718be8SEnji Cooper ATF_REQUIRE(close(fds[1]) == 0); 150*57718be8SEnji Cooper } 151*57718be8SEnji Cooper 152*57718be8SEnji Cooper static void 153*57718be8SEnji Cooper map_sighandler(int signo) 154*57718be8SEnji Cooper { 155*57718be8SEnji Cooper _exit(signo); 156*57718be8SEnji Cooper } 157*57718be8SEnji Cooper 158*57718be8SEnji Cooper ATF_TC(mmap_block); 159*57718be8SEnji Cooper ATF_TC_HEAD(mmap_block, tc) 160*57718be8SEnji Cooper { 161*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) with a block device"); 162*57718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 163*57718be8SEnji Cooper } 164*57718be8SEnji Cooper 165*57718be8SEnji Cooper ATF_TC_BODY(mmap_block, tc) 166*57718be8SEnji Cooper { 167*57718be8SEnji Cooper static const int mib[] = { CTL_HW, HW_DISKNAMES }; 168*57718be8SEnji Cooper static const unsigned int miblen = __arraycount(mib); 169*57718be8SEnji Cooper char *map, *dk, *drives, dev[PATH_MAX]; 170*57718be8SEnji Cooper size_t len; 171*57718be8SEnji Cooper int fd = -1; 172*57718be8SEnji Cooper 173*57718be8SEnji Cooper atf_tc_skip("The test case causes a panic (PR kern/38889, kern/46592)"); 174*57718be8SEnji Cooper 175*57718be8SEnji Cooper ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0); 176*57718be8SEnji Cooper drives = malloc(len); 177*57718be8SEnji Cooper ATF_REQUIRE(drives != NULL); 178*57718be8SEnji Cooper ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0); 179*57718be8SEnji Cooper for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) { 180*57718be8SEnji Cooper sprintf(dev, _PATH_DEV "%s%c", dk, 'a'+RAW_PART); 181*57718be8SEnji Cooper fprintf(stderr, "trying: %s\n", dev); 182*57718be8SEnji Cooper 183*57718be8SEnji Cooper if ((fd = open(dev, O_RDONLY)) >= 0) { 184*57718be8SEnji Cooper (void)fprintf(stderr, "using %s\n", dev); 185*57718be8SEnji Cooper break; 186*57718be8SEnji Cooper } 187*57718be8SEnji Cooper } 188*57718be8SEnji Cooper free(drives); 189*57718be8SEnji Cooper 190*57718be8SEnji Cooper if (fd < 0) 191*57718be8SEnji Cooper atf_tc_skip("failed to find suitable block device"); 192*57718be8SEnji Cooper 193*57718be8SEnji Cooper map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0); 194*57718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 195*57718be8SEnji Cooper 196*57718be8SEnji Cooper (void)fprintf(stderr, "first byte %x\n", *map); 197*57718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 198*57718be8SEnji Cooper (void)fprintf(stderr, "first byte %x\n", *map); 199*57718be8SEnji Cooper 200*57718be8SEnji Cooper ATF_REQUIRE(munmap(map, 4096) == 0); 201*57718be8SEnji Cooper } 202*57718be8SEnji Cooper 203*57718be8SEnji Cooper ATF_TC(mmap_err); 204*57718be8SEnji Cooper ATF_TC_HEAD(mmap_err, tc) 205*57718be8SEnji Cooper { 206*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)"); 207*57718be8SEnji Cooper } 208*57718be8SEnji Cooper 209*57718be8SEnji Cooper ATF_TC_BODY(mmap_err, tc) 210*57718be8SEnji Cooper { 211*57718be8SEnji Cooper size_t addr = SIZE_MAX; 212*57718be8SEnji Cooper void *map; 213*57718be8SEnji Cooper 214*57718be8SEnji Cooper errno = 0; 215*57718be8SEnji Cooper map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0); 216*57718be8SEnji Cooper 217*57718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 218*57718be8SEnji Cooper ATF_REQUIRE(errno == EBADF); 219*57718be8SEnji Cooper 220*57718be8SEnji Cooper errno = 0; 221*57718be8SEnji Cooper map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0); 222*57718be8SEnji Cooper 223*57718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 224*57718be8SEnji Cooper ATF_REQUIRE(errno == EINVAL); 225*57718be8SEnji Cooper 226*57718be8SEnji Cooper errno = 0; 227*57718be8SEnji Cooper map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0); 228*57718be8SEnji Cooper 229*57718be8SEnji Cooper ATF_REQUIRE(map == MAP_FAILED); 230*57718be8SEnji Cooper ATF_REQUIRE(errno == EINVAL); 231*57718be8SEnji Cooper } 232*57718be8SEnji Cooper 233*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_loan); 234*57718be8SEnji Cooper ATF_TC_HEAD(mmap_loan, tc) 235*57718be8SEnji Cooper { 236*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)"); 237*57718be8SEnji Cooper } 238*57718be8SEnji Cooper 239*57718be8SEnji Cooper ATF_TC_BODY(mmap_loan, tc) 240*57718be8SEnji Cooper { 241*57718be8SEnji Cooper char buf[BUFSIZE]; 242*57718be8SEnji Cooper char *vp, *vp2; 243*57718be8SEnji Cooper int fd; 244*57718be8SEnji Cooper 245*57718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0600); 246*57718be8SEnji Cooper ATF_REQUIRE(fd >= 0); 247*57718be8SEnji Cooper 248*57718be8SEnji Cooper (void)memset(buf, 'x', sizeof(buf)); 249*57718be8SEnji Cooper (void)write(fd, buf, sizeof(buf)); 250*57718be8SEnji Cooper 251*57718be8SEnji Cooper vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 252*57718be8SEnji Cooper MAP_FILE | MAP_PRIVATE, fd, 0); 253*57718be8SEnji Cooper 254*57718be8SEnji Cooper ATF_REQUIRE(vp != MAP_FAILED); 255*57718be8SEnji Cooper 256*57718be8SEnji Cooper vp2 = vp; 257*57718be8SEnji Cooper 258*57718be8SEnji Cooper testloan(vp, vp2, 'A', 0); 259*57718be8SEnji Cooper testloan(vp, vp2, 'B', 1); 260*57718be8SEnji Cooper 261*57718be8SEnji Cooper ATF_REQUIRE(munmap(vp, BUFSIZE) == 0); 262*57718be8SEnji Cooper 263*57718be8SEnji Cooper vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 264*57718be8SEnji Cooper MAP_FILE | MAP_SHARED, fd, 0); 265*57718be8SEnji Cooper 266*57718be8SEnji Cooper vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 267*57718be8SEnji Cooper MAP_FILE | MAP_SHARED, fd, 0); 268*57718be8SEnji Cooper 269*57718be8SEnji Cooper ATF_REQUIRE(vp != MAP_FAILED); 270*57718be8SEnji Cooper ATF_REQUIRE(vp2 != MAP_FAILED); 271*57718be8SEnji Cooper 272*57718be8SEnji Cooper testloan(vp, vp2, 'E', 1); 273*57718be8SEnji Cooper 274*57718be8SEnji Cooper ATF_REQUIRE(munmap(vp, BUFSIZE) == 0); 275*57718be8SEnji Cooper ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0); 276*57718be8SEnji Cooper } 277*57718be8SEnji Cooper 278*57718be8SEnji Cooper ATF_TC_CLEANUP(mmap_loan, tc) 279*57718be8SEnji Cooper { 280*57718be8SEnji Cooper (void)unlink(path); 281*57718be8SEnji Cooper } 282*57718be8SEnji Cooper 283*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_prot_1); 284*57718be8SEnji Cooper ATF_TC_HEAD(mmap_prot_1, tc) 285*57718be8SEnji Cooper { 286*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1"); 287*57718be8SEnji Cooper } 288*57718be8SEnji Cooper 289*57718be8SEnji Cooper ATF_TC_BODY(mmap_prot_1, tc) 290*57718be8SEnji Cooper { 291*57718be8SEnji Cooper void *map; 292*57718be8SEnji Cooper int fd; 293*57718be8SEnji Cooper 294*57718be8SEnji Cooper /* 295*57718be8SEnji Cooper * Open a file write-only and try to 296*57718be8SEnji Cooper * map it read-only. This should fail. 297*57718be8SEnji Cooper */ 298*57718be8SEnji Cooper fd = open(path, O_WRONLY | O_CREAT, 0700); 299*57718be8SEnji Cooper 300*57718be8SEnji Cooper if (fd < 0) 301*57718be8SEnji Cooper return; 302*57718be8SEnji Cooper 303*57718be8SEnji Cooper ATF_REQUIRE(write(fd, "XXX", 3) == 3); 304*57718be8SEnji Cooper 305*57718be8SEnji Cooper map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0); 306*57718be8SEnji Cooper map_check(map, 1); 307*57718be8SEnji Cooper 308*57718be8SEnji Cooper map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); 309*57718be8SEnji Cooper map_check(map, 0); 310*57718be8SEnji Cooper 311*57718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 312*57718be8SEnji Cooper } 313*57718be8SEnji Cooper 314*57718be8SEnji Cooper ATF_TC_CLEANUP(mmap_prot_1, tc) 315*57718be8SEnji Cooper { 316*57718be8SEnji Cooper (void)unlink(path); 317*57718be8SEnji Cooper } 318*57718be8SEnji Cooper 319*57718be8SEnji Cooper ATF_TC(mmap_prot_2); 320*57718be8SEnji Cooper ATF_TC_HEAD(mmap_prot_2, tc) 321*57718be8SEnji Cooper { 322*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2"); 323*57718be8SEnji Cooper } 324*57718be8SEnji Cooper 325*57718be8SEnji Cooper ATF_TC_BODY(mmap_prot_2, tc) 326*57718be8SEnji Cooper { 327*57718be8SEnji Cooper char buf[2]; 328*57718be8SEnji Cooper void *map; 329*57718be8SEnji Cooper pid_t pid; 330*57718be8SEnji Cooper int sta; 331*57718be8SEnji Cooper 332*57718be8SEnji Cooper /* 333*57718be8SEnji Cooper * Make a PROT_NONE mapping and try to access it. 334*57718be8SEnji Cooper * If we catch a SIGSEGV, all works as expected. 335*57718be8SEnji Cooper */ 336*57718be8SEnji Cooper map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 337*57718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 338*57718be8SEnji Cooper 339*57718be8SEnji Cooper pid = fork(); 340*57718be8SEnji Cooper ATF_REQUIRE(pid >= 0); 341*57718be8SEnji Cooper 342*57718be8SEnji Cooper if (pid == 0) { 343*57718be8SEnji Cooper ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR); 344*57718be8SEnji Cooper ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0); 345*57718be8SEnji Cooper } 346*57718be8SEnji Cooper 347*57718be8SEnji Cooper (void)wait(&sta); 348*57718be8SEnji Cooper 349*57718be8SEnji Cooper ATF_REQUIRE(WIFEXITED(sta) != 0); 350*57718be8SEnji Cooper ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV); 351*57718be8SEnji Cooper ATF_REQUIRE(munmap(map, page) == 0); 352*57718be8SEnji Cooper } 353*57718be8SEnji Cooper 354*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_prot_3); 355*57718be8SEnji Cooper ATF_TC_HEAD(mmap_prot_3, tc) 356*57718be8SEnji Cooper { 357*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3"); 358*57718be8SEnji Cooper } 359*57718be8SEnji Cooper 360*57718be8SEnji Cooper ATF_TC_BODY(mmap_prot_3, tc) 361*57718be8SEnji Cooper { 362*57718be8SEnji Cooper char buf[2]; 363*57718be8SEnji Cooper int fd, sta; 364*57718be8SEnji Cooper void *map; 365*57718be8SEnji Cooper pid_t pid; 366*57718be8SEnji Cooper 367*57718be8SEnji Cooper /* 368*57718be8SEnji Cooper * Open a file, change the permissions 369*57718be8SEnji Cooper * to read-only, and try to map it as 370*57718be8SEnji Cooper * PROT_NONE. This should succeed, but 371*57718be8SEnji Cooper * the access should generate SIGSEGV. 372*57718be8SEnji Cooper */ 373*57718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0700); 374*57718be8SEnji Cooper 375*57718be8SEnji Cooper if (fd < 0) 376*57718be8SEnji Cooper return; 377*57718be8SEnji Cooper 378*57718be8SEnji Cooper ATF_REQUIRE(write(fd, "XXX", 3) == 3); 379*57718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 380*57718be8SEnji Cooper ATF_REQUIRE(chmod(path, 0444) == 0); 381*57718be8SEnji Cooper 382*57718be8SEnji Cooper fd = open(path, O_RDONLY); 383*57718be8SEnji Cooper ATF_REQUIRE(fd != -1); 384*57718be8SEnji Cooper 385*57718be8SEnji Cooper map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0); 386*57718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 387*57718be8SEnji Cooper 388*57718be8SEnji Cooper pid = fork(); 389*57718be8SEnji Cooper 390*57718be8SEnji Cooper ATF_REQUIRE(pid >= 0); 391*57718be8SEnji Cooper 392*57718be8SEnji Cooper if (pid == 0) { 393*57718be8SEnji Cooper ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR); 394*57718be8SEnji Cooper ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0); 395*57718be8SEnji Cooper } 396*57718be8SEnji Cooper 397*57718be8SEnji Cooper (void)wait(&sta); 398*57718be8SEnji Cooper 399*57718be8SEnji Cooper ATF_REQUIRE(WIFEXITED(sta) != 0); 400*57718be8SEnji Cooper ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV); 401*57718be8SEnji Cooper ATF_REQUIRE(munmap(map, 3) == 0); 402*57718be8SEnji Cooper } 403*57718be8SEnji Cooper 404*57718be8SEnji Cooper ATF_TC_CLEANUP(mmap_prot_3, tc) 405*57718be8SEnji Cooper { 406*57718be8SEnji Cooper (void)unlink(path); 407*57718be8SEnji Cooper } 408*57718be8SEnji Cooper 409*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(mmap_truncate); 410*57718be8SEnji Cooper ATF_TC_HEAD(mmap_truncate, tc) 411*57718be8SEnji Cooper { 412*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)"); 413*57718be8SEnji Cooper } 414*57718be8SEnji Cooper 415*57718be8SEnji Cooper ATF_TC_BODY(mmap_truncate, tc) 416*57718be8SEnji Cooper { 417*57718be8SEnji Cooper char *map; 418*57718be8SEnji Cooper long i; 419*57718be8SEnji Cooper int fd; 420*57718be8SEnji Cooper 421*57718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0700); 422*57718be8SEnji Cooper 423*57718be8SEnji Cooper if (fd < 0) 424*57718be8SEnji Cooper return; 425*57718be8SEnji Cooper 426*57718be8SEnji Cooper /* 427*57718be8SEnji Cooper * See that ftruncate(2) works 428*57718be8SEnji Cooper * while the file is mapped. 429*57718be8SEnji Cooper */ 430*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page) == 0); 431*57718be8SEnji Cooper 432*57718be8SEnji Cooper map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE, 433*57718be8SEnji Cooper fd, 0); 434*57718be8SEnji Cooper ATF_REQUIRE(map != MAP_FAILED); 435*57718be8SEnji Cooper 436*57718be8SEnji Cooper for (i = 0; i < page; i++) 437*57718be8SEnji Cooper map[i] = 'x'; 438*57718be8SEnji Cooper 439*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, 0) == 0); 440*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 8) == 0); 441*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 4) == 0); 442*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 2) == 0); 443*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 12) == 0); 444*57718be8SEnji Cooper ATF_REQUIRE(ftruncate(fd, page / 64) == 0); 445*57718be8SEnji Cooper 446*57718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 447*57718be8SEnji Cooper } 448*57718be8SEnji Cooper 449*57718be8SEnji Cooper ATF_TC_CLEANUP(mmap_truncate, tc) 450*57718be8SEnji Cooper { 451*57718be8SEnji Cooper (void)unlink(path); 452*57718be8SEnji Cooper } 453*57718be8SEnji Cooper 454*57718be8SEnji Cooper ATF_TC(mmap_va0); 455*57718be8SEnji Cooper ATF_TC_HEAD(mmap_va0, tc) 456*57718be8SEnji Cooper { 457*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable"); 458*57718be8SEnji Cooper } 459*57718be8SEnji Cooper 460*57718be8SEnji Cooper ATF_TC_BODY(mmap_va0, tc) 461*57718be8SEnji Cooper { 462*57718be8SEnji Cooper int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE; 463*57718be8SEnji Cooper size_t len = sizeof(int); 464*57718be8SEnji Cooper void *map; 465*57718be8SEnji Cooper int val; 466*57718be8SEnji Cooper 467*57718be8SEnji Cooper /* 468*57718be8SEnji Cooper * Make an anonymous fixed mapping at zero address. If the address 469*57718be8SEnji Cooper * is restricted as noted in security(7), the syscall should fail. 470*57718be8SEnji Cooper */ 471*57718be8SEnji Cooper if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0) 472*57718be8SEnji Cooper atf_tc_fail("failed to read vm.user_va0_disable"); 473*57718be8SEnji Cooper 474*57718be8SEnji Cooper map = mmap(NULL, page, PROT_EXEC, flags, -1, 0); 475*57718be8SEnji Cooper map_check(map, val); 476*57718be8SEnji Cooper 477*57718be8SEnji Cooper map = mmap(NULL, page, PROT_READ, flags, -1, 0); 478*57718be8SEnji Cooper map_check(map, val); 479*57718be8SEnji Cooper 480*57718be8SEnji Cooper map = mmap(NULL, page, PROT_WRITE, flags, -1, 0); 481*57718be8SEnji Cooper map_check(map, val); 482*57718be8SEnji Cooper 483*57718be8SEnji Cooper map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0); 484*57718be8SEnji Cooper map_check(map, val); 485*57718be8SEnji Cooper 486*57718be8SEnji Cooper map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0); 487*57718be8SEnji Cooper map_check(map, val); 488*57718be8SEnji Cooper } 489*57718be8SEnji Cooper 490*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 491*57718be8SEnji Cooper { 492*57718be8SEnji Cooper page = sysconf(_SC_PAGESIZE); 493*57718be8SEnji Cooper ATF_REQUIRE(page >= 0); 494*57718be8SEnji Cooper 495*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_block); 496*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_err); 497*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_loan); 498*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_prot_1); 499*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_prot_2); 500*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_prot_3); 501*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_truncate); 502*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mmap_va0); 503*57718be8SEnji Cooper 504*57718be8SEnji Cooper return atf_no_error(); 505*57718be8SEnji Cooper } 506