mmap_test.c revision 288466
1214503Srpaulo/*- 2214503Srpaulo * Copyright (c) 2009 Simon L. Nielsen <simon@FreeBSD.org>, 3252726Srpaulo * Bjoern A. Zeeb <bz@FreeBSD.org> 4214503Srpaulo * 5252726Srpaulo * Redistribution and use in source and binary forms, with or without 6252726Srpaulo * modification, are permitted provided that the following conditions 7214503Srpaulo * are met: 8214503Srpaulo * 1. Redistributions of source code must retain the above copyright 9214503Srpaulo * notice, this list of conditions and the following disclaimer. 10214503Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 11214503Srpaulo * notice, this list of conditions and the following disclaimer in the 12214503Srpaulo * documentation and/or other materials provided with the distribution. 13214503Srpaulo * 14214503Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15214503Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16252726Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17214503Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18214503Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19214503Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20214503Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21214503Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22214503Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23214503Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24252726Srpaulo * SUCH DAMAGE. 25214503Srpaulo * 26214503Srpaulo * $FreeBSD: stable/10/tests/sys/vm/mmap_test.c 288466 2015-10-01 22:17:27Z jhb $ 27214503Srpaulo */ 28214503Srpaulo 29214503Srpaulo#include <sys/param.h> 30214503Srpaulo#include <sys/mman.h> 31214503Srpaulo#include <sys/sysctl.h> 32214503Srpaulo 33214503Srpaulo#include <atf-c.h> 34214503Srpaulo#include <errno.h> 35252726Srpaulo#include <fcntl.h> 36214503Srpaulo#include <stdarg.h> 37252726Srpaulo#include <stdio.h> 38252726Srpaulo#include <stdlib.h> 39252726Srpaulo 40252726Srpaulostatic const struct { 41214503Srpaulo void *addr; 42214503Srpaulo int ok[2]; /* Depending on security.bsd.map_at_zero {0, !=0}. */ 43252726Srpaulo} map_at_zero_tests[] = { 44214503Srpaulo { (void *)0, { 0, 1 } }, /* Test sysctl. */ 45214503Srpaulo { (void *)1, { 0, 0 } }, 46214503Srpaulo { (void *)(PAGE_SIZE - 1), { 0, 0 } }, 47214503Srpaulo { (void *)PAGE_SIZE, { 1, 1 } }, 48214503Srpaulo { (void *)-1, { 0, 0 } }, 49214503Srpaulo { (void *)(-PAGE_SIZE), { 0, 0 } }, 50214503Srpaulo { (void *)(-1 - PAGE_SIZE), { 0, 0 } }, 51214503Srpaulo { (void *)(-1 - PAGE_SIZE - 1), { 0, 0 } }, 52214503Srpaulo { (void *)(0x1000 * PAGE_SIZE), { 1, 1 } }, 53214503Srpaulo}; 54214503Srpaulo 55214503Srpaulo#define MAP_AT_ZERO "security.bsd.map_at_zero" 56214503Srpaulo 57214503SrpauloATF_TC_WITHOUT_HEAD(mmap__map_at_zero); 58214503SrpauloATF_TC_BODY(mmap__map_at_zero, tc) 59214503Srpaulo{ 60214503Srpaulo void *p; 61214503Srpaulo size_t len; 62214503Srpaulo unsigned int i; 63214503Srpaulo int map_at_zero; 64214503Srpaulo 65214503Srpaulo len = sizeof(map_at_zero); 66214503Srpaulo if (sysctlbyname(MAP_AT_ZERO, &map_at_zero, &len, NULL, 0) == -1) { 67214503Srpaulo atf_tc_skip("sysctl for %s failed: %s\n", MAP_AT_ZERO, 68214503Srpaulo strerror(errno)); 69214503Srpaulo return; 70214503Srpaulo } 71214503Srpaulo 72214503Srpaulo /* Normalize to 0 or 1 for array access. */ 73214503Srpaulo map_at_zero = !!map_at_zero; 74214503Srpaulo 75214503Srpaulo for (i = 0; i < nitems(map_at_zero_tests); i++) { 76214503Srpaulo p = mmap((void *)map_at_zero_tests[i].addr, PAGE_SIZE, 77214503Srpaulo PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED, 78214503Srpaulo -1, 0); 79214503Srpaulo if (p == MAP_FAILED) { 80214503Srpaulo ATF_CHECK_MSG(map_at_zero_tests[i].ok[map_at_zero] == 0, 81214503Srpaulo "mmap(%p, ...) failed", map_at_zero_tests[i].addr); 82214503Srpaulo } else { 83214503Srpaulo ATF_CHECK_MSG(map_at_zero_tests[i].ok[map_at_zero] == 1, 84214503Srpaulo "mmap(%p, ...) succeeded: p=%p\n", 85214503Srpaulo map_at_zero_tests[i].addr, p); 86214503Srpaulo } 87214503Srpaulo } 88214503Srpaulo} 89214503Srpaulo 90214503Srpaulostatic void 91214503Srpaulochecked_mmap(int prot, int flags, int fd, int error, const char *msg) 92214503Srpaulo{ 93214503Srpaulo void *p; 94214503Srpaulo 95214503Srpaulo p = mmap(NULL, getpagesize(), prot, flags, fd, 0); 96214503Srpaulo if (p == MAP_FAILED) { 97214503Srpaulo if (error == 0) 98214503Srpaulo ATF_CHECK_MSG(0, "%s failed with errno %d", msg, 99214503Srpaulo errno); 100214503Srpaulo else 101214503Srpaulo ATF_CHECK_EQ_MSG(error, errno, 102214503Srpaulo "%s failed with wrong errno %d (expected %d)", msg, 103214503Srpaulo errno, error); 104214503Srpaulo } else { 105214503Srpaulo ATF_CHECK_MSG(error == 0, "%s succeeded", msg); 106214503Srpaulo munmap(p, getpagesize()); 107214503Srpaulo } 108214503Srpaulo} 109214503Srpaulo 110214503SrpauloATF_TC_WITHOUT_HEAD(mmap__bad_arguments); 111214503SrpauloATF_TC_BODY(mmap__bad_arguments, tc) 112214503Srpaulo{ 113214503Srpaulo int fd; 114214503Srpaulo 115214503Srpaulo ATF_REQUIRE((fd = shm_open(SHM_ANON, O_RDWR, 0644)) >= 0); 116214503Srpaulo ATF_REQUIRE(ftruncate(fd, getpagesize()) == 0); 117214503Srpaulo 118214503Srpaulo /* These should work. */ 119214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON, -1, 0, 120214503Srpaulo "simple MAP_ANON"); 121214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0, 122214503Srpaulo "simple shm fd shared"); 123214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0, 124214503Srpaulo "simple shm fd private"); 125214503Srpaulo 126214503Srpaulo#if 0 127214503Srpaulo /* 128214503Srpaulo * These tests do not fail without r271635 and followup fixes. 129214503Srpaulo * Those changes will not be merged to stable/10 since they 130214503Srpaulo * are potentially disruptive. 131214503Srpaulo */ 132214503Srpaulo 133214503Srpaulo /* Extra PROT flags. */ 134214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE | 0x100000, MAP_ANON, -1, EINVAL, 135214503Srpaulo "MAP_ANON with extra PROT flags"); 136214503Srpaulo checked_mmap(0xffff, MAP_SHARED, fd, EINVAL, 137214503Srpaulo "shm fd with garbage PROT"); 138214503Srpaulo 139214503Srpaulo /* Undefined flag. */ 140214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_RESERVED0080, -1, 141214503Srpaulo EINVAL, "Undefined flag"); 142214503Srpaulo 143214503Srpaulo /* Both MAP_SHARED and MAP_PRIVATE */ 144214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | 145214503Srpaulo MAP_SHARED, -1, EINVAL, "MAP_ANON with both SHARED and PRIVATE"); 146214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_SHARED, fd, 147214503Srpaulo EINVAL, "shm fd with both SHARED and PRIVATE"); 148214503Srpaulo 149214503Srpaulo /* At least one of MAP_SHARED or MAP_PRIVATE without ANON */ 150214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, 0, fd, EINVAL, 151214503Srpaulo "shm fd without sharing flag"); 152214503Srpaulo#endif 153214503Srpaulo 154214503Srpaulo /* MAP_ANON with either sharing flag (impacts fork). */ 155214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0, 156214503Srpaulo "shared MAP_ANON"); 157214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0, 158214503Srpaulo "private MAP_ANON"); 159214503Srpaulo 160214503Srpaulo /* MAP_ANON should require an fd of -1. */ 161214503Srpaulo checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, EINVAL, 162214503Srpaulo "MAP_ANON with fd != -1"); 163214503Srpaulo} 164214503Srpaulo 165214503SrpauloATF_TP_ADD_TCS(tp) 166214503Srpaulo{ 167214503Srpaulo 168214503Srpaulo ATF_TP_ADD_TC(tp, mmap__map_at_zero); 169214503Srpaulo ATF_TP_ADD_TC(tp, mmap__bad_arguments); 170214503Srpaulo 171214503Srpaulo return (atf_no_error()); 172214503Srpaulo} 173214503Srpaulo