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