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