1272343Sngie/* $NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Jukka Ruohonen. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie 32272343Sngie/*- 33272343Sngie * Copyright (c)2004 YAMAMOTO Takashi, 34272343Sngie * All rights reserved. 35272343Sngie * 36272343Sngie * Redistribution and use in source and binary forms, with or without 37272343Sngie * modification, are permitted provided that the following conditions 38272343Sngie * are met: 39272343Sngie * 1. Redistributions of source code must retain the above copyright 40272343Sngie * notice, this list of conditions and the following disclaimer. 41272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 42272343Sngie * notice, this list of conditions and the following disclaimer in the 43272343Sngie * documentation and/or other materials provided with the distribution. 44272343Sngie * 45272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55272343Sngie * SUCH DAMAGE. 56272343Sngie */ 57272343Sngie#include <sys/cdefs.h> 58272343Sngie__RCSID("$NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $"); 59272343Sngie 60272343Sngie#include <sys/param.h> 61272343Sngie#include <sys/mman.h> 62272343Sngie#include <sys/socket.h> 63272343Sngie#include <sys/sysctl.h> 64272343Sngie#include <sys/wait.h> 65272343Sngie 66272343Sngie#include <atf-c.h> 67272343Sngie#include <errno.h> 68272343Sngie#include <fcntl.h> 69272343Sngie#include <signal.h> 70272343Sngie#include <stdio.h> 71272343Sngie#include <stdlib.h> 72272343Sngie#include <string.h> 73272343Sngie#include <unistd.h> 74272343Sngie#include <paths.h> 75273525Sngie#ifdef __NetBSD__ 76272343Sngie#include <machine/disklabel.h> 77273525Sngie#endif 78272343Sngie 79273525Sngie#ifdef __FreeBSD__ 80273525Sngie#include <sys/disklabel.h> 81273525Sngie#include <sys/stat.h> 82273525Sngie#include <stdint.h> 83273525Sngie#endif 84273525Sngie 85272343Sngiestatic long page = 0; 86272343Sngiestatic char path[] = "mmap"; 87272343Sngiestatic void map_check(void *, int); 88272343Sngiestatic void map_sighandler(int); 89272343Sngiestatic void testloan(void *, void *, char, int); 90272343Sngie 91272343Sngie#define BUFSIZE (32 * 1024) /* enough size to trigger sosend_loan */ 92272343Sngie 93272343Sngiestatic void 94272343Sngiemap_check(void *map, int flag) 95272343Sngie{ 96272343Sngie 97272343Sngie if (flag != 0) { 98272343Sngie ATF_REQUIRE(map == MAP_FAILED); 99272343Sngie return; 100272343Sngie } 101272343Sngie 102272343Sngie ATF_REQUIRE(map != MAP_FAILED); 103272343Sngie ATF_REQUIRE(munmap(map, page) == 0); 104272343Sngie} 105272343Sngie 106272343Sngievoid 107272343Sngietestloan(void *vp, void *vp2, char pat, int docheck) 108272343Sngie{ 109272343Sngie char buf[BUFSIZE]; 110272343Sngie char backup[BUFSIZE]; 111272343Sngie ssize_t nwritten; 112272343Sngie ssize_t nread; 113272343Sngie int fds[2]; 114272343Sngie int val; 115272343Sngie 116272343Sngie val = BUFSIZE; 117272343Sngie 118272343Sngie if (docheck != 0) 119272343Sngie (void)memcpy(backup, vp, BUFSIZE); 120272343Sngie 121272343Sngie if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds) != 0) 122272343Sngie atf_tc_fail("socketpair() failed"); 123272343Sngie 124272343Sngie val = BUFSIZE; 125272343Sngie 126272343Sngie if (setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0) 127272343Sngie atf_tc_fail("setsockopt() failed, SO_RCVBUF"); 128272343Sngie 129272343Sngie val = BUFSIZE; 130272343Sngie 131272343Sngie if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0) 132272343Sngie atf_tc_fail("setsockopt() failed, SO_SNDBUF"); 133272343Sngie 134272343Sngie if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != 0) 135272343Sngie atf_tc_fail("fcntl() failed"); 136272343Sngie 137272343Sngie nwritten = write(fds[0], (char *)vp + page, BUFSIZE - page); 138272343Sngie 139272343Sngie if (nwritten == -1) 140272343Sngie atf_tc_fail("write() failed"); 141272343Sngie 142272343Sngie /* Break loan. */ 143272343Sngie (void)memset(vp2, pat, BUFSIZE); 144272343Sngie 145272343Sngie nread = read(fds[1], buf + page, BUFSIZE - page); 146272343Sngie 147272343Sngie if (nread == -1) 148272343Sngie atf_tc_fail("read() failed"); 149272343Sngie 150272343Sngie if (nread != nwritten) 151272343Sngie atf_tc_fail("too short read"); 152272343Sngie 153272343Sngie if (docheck != 0 && memcmp(backup, buf + page, nread) != 0) 154272343Sngie atf_tc_fail("data mismatch"); 155272343Sngie 156272343Sngie ATF_REQUIRE(close(fds[0]) == 0); 157272343Sngie ATF_REQUIRE(close(fds[1]) == 0); 158272343Sngie} 159272343Sngie 160272343Sngiestatic void 161272343Sngiemap_sighandler(int signo) 162272343Sngie{ 163272343Sngie _exit(signo); 164272343Sngie} 165272343Sngie 166273525Sngie#ifdef __NetBSD__ 167272343SngieATF_TC(mmap_block); 168272343SngieATF_TC_HEAD(mmap_block, tc) 169272343Sngie{ 170272343Sngie atf_tc_set_md_var(tc, "descr", "Test mmap(2) with a block device"); 171272343Sngie atf_tc_set_md_var(tc, "require.user", "root"); 172272343Sngie} 173272343Sngie 174272343SngieATF_TC_BODY(mmap_block, tc) 175272343Sngie{ 176272343Sngie static const int mib[] = { CTL_HW, HW_DISKNAMES }; 177272343Sngie static const unsigned int miblen = __arraycount(mib); 178272343Sngie char *map, *dk, *drives, dev[PATH_MAX]; 179272343Sngie size_t len; 180272343Sngie int fd = -1; 181272343Sngie 182272343Sngie atf_tc_skip("The test case causes a panic (PR kern/38889, kern/46592)"); 183272343Sngie 184272343Sngie ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0); 185272343Sngie drives = malloc(len); 186272343Sngie ATF_REQUIRE(drives != NULL); 187272343Sngie ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0); 188272343Sngie for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) { 189272343Sngie sprintf(dev, _PATH_DEV "%s%c", dk, 'a'+RAW_PART); 190272343Sngie fprintf(stderr, "trying: %s\n", dev); 191272343Sngie 192272343Sngie if ((fd = open(dev, O_RDONLY)) >= 0) { 193272343Sngie (void)fprintf(stderr, "using %s\n", dev); 194272343Sngie break; 195272343Sngie } 196272343Sngie } 197272343Sngie free(drives); 198272343Sngie 199272343Sngie if (fd < 0) 200272343Sngie atf_tc_skip("failed to find suitable block device"); 201272343Sngie 202272343Sngie map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0); 203272343Sngie ATF_REQUIRE(map != MAP_FAILED); 204272343Sngie 205272343Sngie (void)fprintf(stderr, "first byte %x\n", *map); 206272343Sngie ATF_REQUIRE(close(fd) == 0); 207272343Sngie (void)fprintf(stderr, "first byte %x\n", *map); 208272343Sngie 209272343Sngie ATF_REQUIRE(munmap(map, 4096) == 0); 210272343Sngie} 211273525Sngie#endif 212272343Sngie 213272343SngieATF_TC(mmap_err); 214272343SngieATF_TC_HEAD(mmap_err, tc) 215272343Sngie{ 216272343Sngie atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)"); 217272343Sngie} 218272343Sngie 219272343SngieATF_TC_BODY(mmap_err, tc) 220272343Sngie{ 221272343Sngie size_t addr = SIZE_MAX; 222272343Sngie void *map; 223272343Sngie 224272343Sngie errno = 0; 225272343Sngie map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0); 226272343Sngie 227272343Sngie ATF_REQUIRE(map == MAP_FAILED); 228272343Sngie ATF_REQUIRE(errno == EBADF); 229272343Sngie 230272343Sngie errno = 0; 231272343Sngie map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0); 232272343Sngie 233272343Sngie ATF_REQUIRE(map == MAP_FAILED); 234272343Sngie ATF_REQUIRE(errno == EINVAL); 235272343Sngie 236272343Sngie errno = 0; 237272343Sngie map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0); 238272343Sngie 239272343Sngie ATF_REQUIRE(map == MAP_FAILED); 240272343Sngie ATF_REQUIRE(errno == EINVAL); 241272343Sngie} 242272343Sngie 243272343SngieATF_TC_WITH_CLEANUP(mmap_loan); 244272343SngieATF_TC_HEAD(mmap_loan, tc) 245272343Sngie{ 246272343Sngie atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)"); 247272343Sngie} 248272343Sngie 249272343SngieATF_TC_BODY(mmap_loan, tc) 250272343Sngie{ 251272343Sngie char buf[BUFSIZE]; 252272343Sngie char *vp, *vp2; 253272343Sngie int fd; 254272343Sngie 255272343Sngie fd = open(path, O_RDWR | O_CREAT, 0600); 256272343Sngie ATF_REQUIRE(fd >= 0); 257272343Sngie 258272343Sngie (void)memset(buf, 'x', sizeof(buf)); 259272343Sngie (void)write(fd, buf, sizeof(buf)); 260272343Sngie 261272343Sngie vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 262272343Sngie MAP_FILE | MAP_PRIVATE, fd, 0); 263272343Sngie 264272343Sngie ATF_REQUIRE(vp != MAP_FAILED); 265272343Sngie 266272343Sngie vp2 = vp; 267272343Sngie 268272343Sngie testloan(vp, vp2, 'A', 0); 269272343Sngie testloan(vp, vp2, 'B', 1); 270272343Sngie 271272343Sngie ATF_REQUIRE(munmap(vp, BUFSIZE) == 0); 272272343Sngie 273272343Sngie vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 274272343Sngie MAP_FILE | MAP_SHARED, fd, 0); 275272343Sngie 276272343Sngie vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, 277272343Sngie MAP_FILE | MAP_SHARED, fd, 0); 278272343Sngie 279272343Sngie ATF_REQUIRE(vp != MAP_FAILED); 280272343Sngie ATF_REQUIRE(vp2 != MAP_FAILED); 281272343Sngie 282272343Sngie testloan(vp, vp2, 'E', 1); 283272343Sngie 284272343Sngie ATF_REQUIRE(munmap(vp, BUFSIZE) == 0); 285272343Sngie ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0); 286272343Sngie} 287272343Sngie 288272343SngieATF_TC_CLEANUP(mmap_loan, tc) 289272343Sngie{ 290272343Sngie (void)unlink(path); 291272343Sngie} 292272343Sngie 293272343SngieATF_TC_WITH_CLEANUP(mmap_prot_1); 294272343SngieATF_TC_HEAD(mmap_prot_1, tc) 295272343Sngie{ 296272343Sngie atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1"); 297272343Sngie} 298272343Sngie 299272343SngieATF_TC_BODY(mmap_prot_1, tc) 300272343Sngie{ 301272343Sngie void *map; 302272343Sngie int fd; 303272343Sngie 304272343Sngie /* 305272343Sngie * Open a file write-only and try to 306272343Sngie * map it read-only. This should fail. 307272343Sngie */ 308272343Sngie fd = open(path, O_WRONLY | O_CREAT, 0700); 309272343Sngie 310272343Sngie if (fd < 0) 311272343Sngie return; 312272343Sngie 313272343Sngie ATF_REQUIRE(write(fd, "XXX", 3) == 3); 314272343Sngie 315272343Sngie map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0); 316272343Sngie map_check(map, 1); 317272343Sngie 318272343Sngie map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); 319272343Sngie map_check(map, 0); 320272343Sngie 321272343Sngie ATF_REQUIRE(close(fd) == 0); 322272343Sngie} 323272343Sngie 324272343SngieATF_TC_CLEANUP(mmap_prot_1, tc) 325272343Sngie{ 326272343Sngie (void)unlink(path); 327272343Sngie} 328272343Sngie 329272343SngieATF_TC(mmap_prot_2); 330272343SngieATF_TC_HEAD(mmap_prot_2, tc) 331272343Sngie{ 332272343Sngie atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2"); 333272343Sngie} 334272343Sngie 335272343SngieATF_TC_BODY(mmap_prot_2, tc) 336272343Sngie{ 337272343Sngie char buf[2]; 338272343Sngie void *map; 339272343Sngie pid_t pid; 340272343Sngie int sta; 341272343Sngie 342272343Sngie /* 343272343Sngie * Make a PROT_NONE mapping and try to access it. 344272343Sngie * If we catch a SIGSEGV, all works as expected. 345272343Sngie */ 346272343Sngie map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 347272343Sngie ATF_REQUIRE(map != MAP_FAILED); 348272343Sngie 349272343Sngie pid = fork(); 350272343Sngie ATF_REQUIRE(pid >= 0); 351272343Sngie 352272343Sngie if (pid == 0) { 353272343Sngie ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR); 354272343Sngie ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0); 355272343Sngie } 356272343Sngie 357272343Sngie (void)wait(&sta); 358272343Sngie 359272343Sngie ATF_REQUIRE(WIFEXITED(sta) != 0); 360272343Sngie ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV); 361272343Sngie ATF_REQUIRE(munmap(map, page) == 0); 362272343Sngie} 363272343Sngie 364272343SngieATF_TC_WITH_CLEANUP(mmap_prot_3); 365272343SngieATF_TC_HEAD(mmap_prot_3, tc) 366272343Sngie{ 367272343Sngie atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3"); 368272343Sngie} 369272343Sngie 370272343SngieATF_TC_BODY(mmap_prot_3, tc) 371272343Sngie{ 372272343Sngie char buf[2]; 373272343Sngie int fd, sta; 374272343Sngie void *map; 375272343Sngie pid_t pid; 376272343Sngie 377272343Sngie /* 378272343Sngie * Open a file, change the permissions 379272343Sngie * to read-only, and try to map it as 380272343Sngie * PROT_NONE. This should succeed, but 381272343Sngie * the access should generate SIGSEGV. 382272343Sngie */ 383272343Sngie fd = open(path, O_RDWR | O_CREAT, 0700); 384272343Sngie 385272343Sngie if (fd < 0) 386272343Sngie return; 387272343Sngie 388272343Sngie ATF_REQUIRE(write(fd, "XXX", 3) == 3); 389272343Sngie ATF_REQUIRE(close(fd) == 0); 390272343Sngie ATF_REQUIRE(chmod(path, 0444) == 0); 391272343Sngie 392272343Sngie fd = open(path, O_RDONLY); 393272343Sngie ATF_REQUIRE(fd != -1); 394272343Sngie 395272343Sngie map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0); 396272343Sngie ATF_REQUIRE(map != MAP_FAILED); 397272343Sngie 398272343Sngie pid = fork(); 399272343Sngie 400272343Sngie ATF_REQUIRE(pid >= 0); 401272343Sngie 402272343Sngie if (pid == 0) { 403272343Sngie ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR); 404272343Sngie ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0); 405272343Sngie } 406272343Sngie 407272343Sngie (void)wait(&sta); 408272343Sngie 409272343Sngie ATF_REQUIRE(WIFEXITED(sta) != 0); 410272343Sngie ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV); 411272343Sngie ATF_REQUIRE(munmap(map, 3) == 0); 412272343Sngie} 413272343Sngie 414272343SngieATF_TC_CLEANUP(mmap_prot_3, tc) 415272343Sngie{ 416272343Sngie (void)unlink(path); 417272343Sngie} 418272343Sngie 419272343SngieATF_TC_WITH_CLEANUP(mmap_truncate); 420272343SngieATF_TC_HEAD(mmap_truncate, tc) 421272343Sngie{ 422272343Sngie atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)"); 423272343Sngie} 424272343Sngie 425272343SngieATF_TC_BODY(mmap_truncate, tc) 426272343Sngie{ 427272343Sngie char *map; 428272343Sngie long i; 429272343Sngie int fd; 430272343Sngie 431272343Sngie fd = open(path, O_RDWR | O_CREAT, 0700); 432272343Sngie 433272343Sngie if (fd < 0) 434272343Sngie return; 435272343Sngie 436272343Sngie /* 437272343Sngie * See that ftruncate(2) works 438272343Sngie * while the file is mapped. 439272343Sngie */ 440272343Sngie ATF_REQUIRE(ftruncate(fd, page) == 0); 441272343Sngie 442272343Sngie map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE, 443272343Sngie fd, 0); 444272343Sngie ATF_REQUIRE(map != MAP_FAILED); 445272343Sngie 446272343Sngie for (i = 0; i < page; i++) 447272343Sngie map[i] = 'x'; 448272343Sngie 449272343Sngie ATF_REQUIRE(ftruncate(fd, 0) == 0); 450272343Sngie ATF_REQUIRE(ftruncate(fd, page / 8) == 0); 451272343Sngie ATF_REQUIRE(ftruncate(fd, page / 4) == 0); 452272343Sngie ATF_REQUIRE(ftruncate(fd, page / 2) == 0); 453272343Sngie ATF_REQUIRE(ftruncate(fd, page / 12) == 0); 454272343Sngie ATF_REQUIRE(ftruncate(fd, page / 64) == 0); 455272343Sngie 456272343Sngie ATF_REQUIRE(close(fd) == 0); 457272343Sngie} 458272343Sngie 459272343SngieATF_TC_CLEANUP(mmap_truncate, tc) 460272343Sngie{ 461272343Sngie (void)unlink(path); 462272343Sngie} 463272343Sngie 464272343SngieATF_TC(mmap_va0); 465272343SngieATF_TC_HEAD(mmap_va0, tc) 466272343Sngie{ 467272343Sngie atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable"); 468272343Sngie} 469272343Sngie 470272343SngieATF_TC_BODY(mmap_va0, tc) 471272343Sngie{ 472272343Sngie int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE; 473272343Sngie size_t len = sizeof(int); 474272343Sngie void *map; 475272343Sngie int val; 476272343Sngie 477272343Sngie /* 478272343Sngie * Make an anonymous fixed mapping at zero address. If the address 479272343Sngie * is restricted as noted in security(7), the syscall should fail. 480272343Sngie */ 481273525Sngie#ifdef __FreeBSD__ 482273525Sngie if (sysctlbyname("security.bsd.map_at_zero", &val, &len, NULL, 0) != 0) 483273525Sngie atf_tc_fail("failed to read security.bsd.map_at_zero"); 484273525Sngie val = !val; /* 1 == enable map at zero */ 485273525Sngie#endif 486273525Sngie#ifdef __NetBSD__ 487272343Sngie if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0) 488272343Sngie atf_tc_fail("failed to read vm.user_va0_disable"); 489273525Sngie#endif 490272343Sngie 491272343Sngie map = mmap(NULL, page, PROT_EXEC, flags, -1, 0); 492272343Sngie map_check(map, val); 493272343Sngie 494272343Sngie map = mmap(NULL, page, PROT_READ, flags, -1, 0); 495272343Sngie map_check(map, val); 496272343Sngie 497272343Sngie map = mmap(NULL, page, PROT_WRITE, flags, -1, 0); 498272343Sngie map_check(map, val); 499272343Sngie 500272343Sngie map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0); 501272343Sngie map_check(map, val); 502272343Sngie 503272343Sngie map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0); 504272343Sngie map_check(map, val); 505272343Sngie} 506272343Sngie 507272343SngieATF_TP_ADD_TCS(tp) 508272343Sngie{ 509272343Sngie page = sysconf(_SC_PAGESIZE); 510272343Sngie ATF_REQUIRE(page >= 0); 511272343Sngie 512273525Sngie#ifdef __NetBSD__ 513272343Sngie ATF_TP_ADD_TC(tp, mmap_block); 514273525Sngie#endif 515272343Sngie ATF_TP_ADD_TC(tp, mmap_err); 516272343Sngie ATF_TP_ADD_TC(tp, mmap_loan); 517272343Sngie ATF_TP_ADD_TC(tp, mmap_prot_1); 518272343Sngie ATF_TP_ADD_TC(tp, mmap_prot_2); 519272343Sngie ATF_TP_ADD_TC(tp, mmap_prot_3); 520272343Sngie ATF_TP_ADD_TC(tp, mmap_truncate); 521272343Sngie ATF_TP_ADD_TC(tp, mmap_va0); 522272343Sngie 523272343Sngie return atf_no_error(); 524272343Sngie} 525