Home | History | Annotate | Line # | Download | only in sys
t_mmap.c revision 1.14
      1  1.14    jruoho /* $NetBSD: t_mmap.c,v 1.14 2020/06/26 07:50:11 jruoho 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.14    jruoho __RCSID("$NetBSD: t_mmap.c,v 1.14 2020/06/26 07:50:11 jruoho Exp $");
     59   1.1    jruoho 
     60   1.1    jruoho #include <sys/param.h>
     61  1.12  christos #include <sys/disklabel.h>
     62   1.1    jruoho #include <sys/mman.h>
     63  1.10  christos #include <sys/stat.h>
     64   1.2    jruoho #include <sys/socket.h>
     65   1.1    jruoho #include <sys/sysctl.h>
     66   1.1    jruoho #include <sys/wait.h>
     67   1.1    jruoho 
     68   1.2    jruoho #include <atf-c.h>
     69   1.1    jruoho #include <errno.h>
     70   1.1    jruoho #include <fcntl.h>
     71   1.1    jruoho #include <signal.h>
     72   1.3    jruoho #include <stdio.h>
     73   1.1    jruoho #include <stdlib.h>
     74   1.1    jruoho #include <string.h>
     75   1.1    jruoho #include <unistd.h>
     76   1.5    martin #include <paths.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.14    jruoho 	atf_tc_skip("The test case causes a panic " \
    175  1.14    jruoho 	    "(PR kern/38889, PR kern/46592)");
    176   1.3    jruoho 
    177   1.5    martin 	ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0);
    178   1.5    martin 	drives = malloc(len);
    179   1.5    martin 	ATF_REQUIRE(drives != NULL);
    180   1.5    martin 	ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0);
    181   1.5    martin 	for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) {
    182  1.13  christos 		if (strncmp(dk, "dk", 2) == 0)
    183  1.13  christos 			snprintf(dev, sizeof(dev), _PATH_DEV "%s", dk);
    184  1.13  christos 		else
    185  1.13  christos 			snprintf(dev, sizeof(dev), _PATH_DEV "%s%c", dk,
    186  1.13  christos 			    'a' + RAW_PART);
    187   1.5    martin 		fprintf(stderr, "trying: %s\n", dev);
    188   1.3    jruoho 
    189   1.5    martin 		if ((fd = open(dev, O_RDONLY)) >= 0) {
    190   1.5    martin 			(void)fprintf(stderr, "using %s\n", dev);
    191   1.3    jruoho 			break;
    192  1.13  christos 		} else
    193  1.13  christos 			(void)fprintf(stderr, "%s: %s\n", dev, strerror(errno));
    194   1.3    jruoho 	}
    195   1.5    martin 	free(drives);
    196   1.3    jruoho 
    197   1.5    martin 	if (fd < 0)
    198   1.4    jruoho 		atf_tc_skip("failed to find suitable block device");
    199   1.3    jruoho 
    200   1.3    jruoho 	map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0);
    201  1.13  christos 	ATF_REQUIRE_MSG(map != MAP_FAILED, "mmap: %s", strerror(errno));
    202   1.3    jruoho 
    203   1.3    jruoho 	(void)fprintf(stderr, "first byte %x\n", *map);
    204   1.3    jruoho 	ATF_REQUIRE(close(fd) == 0);
    205   1.3    jruoho 	(void)fprintf(stderr, "first byte %x\n", *map);
    206   1.3    jruoho 
    207   1.3    jruoho 	ATF_REQUIRE(munmap(map, 4096) == 0);
    208   1.3    jruoho }
    209   1.3    jruoho 
    210   1.1    jruoho ATF_TC(mmap_err);
    211   1.1    jruoho ATF_TC_HEAD(mmap_err, tc)
    212   1.1    jruoho {
    213   1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)");
    214   1.1    jruoho }
    215   1.1    jruoho 
    216   1.1    jruoho ATF_TC_BODY(mmap_err, tc)
    217   1.1    jruoho {
    218   1.1    jruoho 	size_t addr = SIZE_MAX;
    219   1.1    jruoho 	void *map;
    220   1.1    jruoho 
    221   1.1    jruoho 	errno = 0;
    222   1.1    jruoho 	map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0);
    223   1.1    jruoho 
    224   1.1    jruoho 	ATF_REQUIRE(map == MAP_FAILED);
    225   1.1    jruoho 	ATF_REQUIRE(errno == EBADF);
    226   1.1    jruoho 
    227   1.1    jruoho 	errno = 0;
    228   1.1    jruoho 	map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 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 	errno = 0;
    234   1.1    jruoho 	map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0);
    235   1.1    jruoho 
    236   1.1    jruoho 	ATF_REQUIRE(map == MAP_FAILED);
    237   1.1    jruoho 	ATF_REQUIRE(errno == EINVAL);
    238   1.1    jruoho }
    239   1.1    jruoho 
    240   1.2    jruoho ATF_TC_WITH_CLEANUP(mmap_loan);
    241   1.2    jruoho ATF_TC_HEAD(mmap_loan, tc)
    242   1.2    jruoho {
    243   1.2    jruoho 	atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)");
    244   1.2    jruoho }
    245   1.2    jruoho 
    246   1.2    jruoho ATF_TC_BODY(mmap_loan, tc)
    247   1.2    jruoho {
    248   1.2    jruoho 	char buf[BUFSIZE];
    249   1.2    jruoho 	char *vp, *vp2;
    250   1.2    jruoho 	int fd;
    251   1.2    jruoho 
    252   1.2    jruoho 	fd = open(path, O_RDWR | O_CREAT, 0600);
    253   1.2    jruoho 	ATF_REQUIRE(fd >= 0);
    254   1.2    jruoho 
    255   1.2    jruoho 	(void)memset(buf, 'x', sizeof(buf));
    256   1.2    jruoho 	(void)write(fd, buf, sizeof(buf));
    257   1.2    jruoho 
    258   1.2    jruoho 	vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
    259   1.2    jruoho 	    MAP_FILE | MAP_PRIVATE, fd, 0);
    260   1.2    jruoho 
    261   1.2    jruoho 	ATF_REQUIRE(vp != MAP_FAILED);
    262   1.2    jruoho 
    263   1.2    jruoho 	vp2 = vp;
    264   1.2    jruoho 
    265   1.2    jruoho 	testloan(vp, vp2, 'A', 0);
    266   1.2    jruoho 	testloan(vp, vp2, 'B', 1);
    267   1.2    jruoho 
    268   1.2    jruoho 	ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
    269   1.2    jruoho 
    270   1.2    jruoho 	vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
    271   1.2    jruoho 	    MAP_FILE | MAP_SHARED, fd, 0);
    272   1.2    jruoho 
    273   1.2    jruoho 	vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
    274   1.2    jruoho 	    MAP_FILE | MAP_SHARED, fd, 0);
    275   1.2    jruoho 
    276   1.2    jruoho 	ATF_REQUIRE(vp != MAP_FAILED);
    277   1.2    jruoho 	ATF_REQUIRE(vp2 != MAP_FAILED);
    278   1.2    jruoho 
    279   1.2    jruoho 	testloan(vp, vp2, 'E', 1);
    280   1.2    jruoho 
    281   1.2    jruoho 	ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
    282   1.2    jruoho 	ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0);
    283   1.2    jruoho }
    284   1.2    jruoho 
    285   1.2    jruoho ATF_TC_CLEANUP(mmap_loan, tc)
    286   1.2    jruoho {
    287   1.2    jruoho 	(void)unlink(path);
    288   1.2    jruoho }
    289   1.2    jruoho 
    290   1.1    jruoho ATF_TC_WITH_CLEANUP(mmap_prot_1);
    291   1.1    jruoho ATF_TC_HEAD(mmap_prot_1, tc)
    292   1.1    jruoho {
    293   1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1");
    294   1.1    jruoho }
    295   1.1    jruoho 
    296   1.1    jruoho ATF_TC_BODY(mmap_prot_1, tc)
    297   1.1    jruoho {
    298   1.1    jruoho 	void *map;
    299   1.1    jruoho 	int fd;
    300   1.1    jruoho 
    301   1.1    jruoho 	/*
    302   1.1    jruoho 	 * Open a file write-only and try to
    303   1.1    jruoho 	 * map it read-only. This should fail.
    304   1.1    jruoho 	 */
    305   1.1    jruoho 	fd = open(path, O_WRONLY | O_CREAT, 0700);
    306   1.1    jruoho 
    307   1.1    jruoho 	if (fd < 0)
    308   1.1    jruoho 		return;
    309   1.1    jruoho 
    310   1.1    jruoho 	ATF_REQUIRE(write(fd, "XXX", 3) == 3);
    311   1.1    jruoho 
    312   1.1    jruoho 	map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
    313   1.1    jruoho 	map_check(map, 1);
    314   1.1    jruoho 
    315   1.1    jruoho 	map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
    316   1.1    jruoho 	map_check(map, 0);
    317   1.1    jruoho 
    318   1.1    jruoho 	ATF_REQUIRE(close(fd) == 0);
    319   1.1    jruoho }
    320   1.1    jruoho 
    321   1.1    jruoho ATF_TC_CLEANUP(mmap_prot_1, tc)
    322   1.1    jruoho {
    323   1.1    jruoho 	(void)unlink(path);
    324   1.1    jruoho }
    325   1.1    jruoho 
    326   1.1    jruoho ATF_TC(mmap_prot_2);
    327   1.1    jruoho ATF_TC_HEAD(mmap_prot_2, tc)
    328   1.1    jruoho {
    329   1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2");
    330   1.1    jruoho }
    331   1.1    jruoho 
    332   1.1    jruoho ATF_TC_BODY(mmap_prot_2, tc)
    333   1.1    jruoho {
    334   1.1    jruoho 	char buf[2];
    335   1.1    jruoho 	void *map;
    336   1.1    jruoho 	pid_t pid;
    337   1.1    jruoho 	int sta;
    338   1.1    jruoho 
    339   1.1    jruoho 	/*
    340   1.1    jruoho 	 * Make a PROT_NONE mapping and try to access it.
    341   1.1    jruoho 	 * If we catch a SIGSEGV, all works as expected.
    342   1.1    jruoho 	 */
    343   1.1    jruoho 	map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
    344   1.1    jruoho 	ATF_REQUIRE(map != MAP_FAILED);
    345   1.1    jruoho 
    346   1.1    jruoho 	pid = fork();
    347   1.1    jruoho 	ATF_REQUIRE(pid >= 0);
    348   1.1    jruoho 
    349   1.1    jruoho 	if (pid == 0) {
    350   1.1    jruoho 		ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
    351   1.1    jruoho 		ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
    352   1.1    jruoho 	}
    353   1.1    jruoho 
    354   1.1    jruoho 	(void)wait(&sta);
    355   1.1    jruoho 
    356   1.1    jruoho 	ATF_REQUIRE(WIFEXITED(sta) != 0);
    357   1.1    jruoho 	ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
    358   1.1    jruoho 	ATF_REQUIRE(munmap(map, page) == 0);
    359   1.1    jruoho }
    360   1.1    jruoho 
    361   1.1    jruoho ATF_TC_WITH_CLEANUP(mmap_prot_3);
    362   1.1    jruoho ATF_TC_HEAD(mmap_prot_3, tc)
    363   1.1    jruoho {
    364   1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3");
    365   1.1    jruoho }
    366   1.1    jruoho 
    367   1.1    jruoho ATF_TC_BODY(mmap_prot_3, tc)
    368   1.1    jruoho {
    369   1.1    jruoho 	char buf[2];
    370   1.1    jruoho 	int fd, sta;
    371   1.1    jruoho 	void *map;
    372   1.1    jruoho 	pid_t pid;
    373   1.1    jruoho 
    374   1.1    jruoho 	/*
    375   1.1    jruoho 	 * Open a file, change the permissions
    376   1.1    jruoho 	 * to read-only, and try to map it as
    377   1.1    jruoho 	 * PROT_NONE. This should succeed, but
    378   1.1    jruoho 	 * the access should generate SIGSEGV.
    379   1.1    jruoho 	 */
    380   1.1    jruoho 	fd = open(path, O_RDWR | O_CREAT, 0700);
    381   1.1    jruoho 
    382   1.1    jruoho 	if (fd < 0)
    383   1.1    jruoho 		return;
    384   1.1    jruoho 
    385   1.1    jruoho 	ATF_REQUIRE(write(fd, "XXX", 3) == 3);
    386   1.1    jruoho 	ATF_REQUIRE(close(fd) == 0);
    387   1.1    jruoho 	ATF_REQUIRE(chmod(path, 0444) == 0);
    388   1.1    jruoho 
    389   1.1    jruoho 	fd = open(path, O_RDONLY);
    390   1.1    jruoho 	ATF_REQUIRE(fd != -1);
    391   1.1    jruoho 
    392   1.1    jruoho 	map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
    393   1.1    jruoho 	ATF_REQUIRE(map != MAP_FAILED);
    394   1.1    jruoho 
    395   1.1    jruoho 	pid = fork();
    396   1.1    jruoho 
    397   1.1    jruoho 	ATF_REQUIRE(pid >= 0);
    398   1.1    jruoho 
    399   1.1    jruoho 	if (pid == 0) {
    400   1.1    jruoho 		ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
    401   1.1    jruoho 		ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
    402   1.1    jruoho 	}
    403   1.1    jruoho 
    404   1.1    jruoho 	(void)wait(&sta);
    405   1.1    jruoho 
    406   1.1    jruoho 	ATF_REQUIRE(WIFEXITED(sta) != 0);
    407   1.1    jruoho 	ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
    408   1.1    jruoho 	ATF_REQUIRE(munmap(map, 3) == 0);
    409   1.1    jruoho }
    410   1.1    jruoho 
    411   1.1    jruoho ATF_TC_CLEANUP(mmap_prot_3, tc)
    412   1.1    jruoho {
    413   1.1    jruoho 	(void)unlink(path);
    414   1.1    jruoho }
    415   1.1    jruoho 
    416   1.1    jruoho ATF_TC_WITH_CLEANUP(mmap_truncate);
    417   1.1    jruoho ATF_TC_HEAD(mmap_truncate, tc)
    418   1.1    jruoho {
    419   1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)");
    420   1.1    jruoho }
    421   1.1    jruoho 
    422   1.1    jruoho ATF_TC_BODY(mmap_truncate, tc)
    423   1.1    jruoho {
    424   1.1    jruoho 	char *map;
    425   1.1    jruoho 	long i;
    426   1.1    jruoho 	int fd;
    427   1.1    jruoho 
    428   1.1    jruoho 	fd = open(path, O_RDWR | O_CREAT, 0700);
    429   1.1    jruoho 
    430   1.1    jruoho 	if (fd < 0)
    431   1.1    jruoho 		return;
    432   1.1    jruoho 
    433   1.1    jruoho 	/*
    434   1.1    jruoho 	 * See that ftruncate(2) works
    435   1.1    jruoho 	 * while the file is mapped.
    436   1.1    jruoho 	 */
    437   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, page) == 0);
    438   1.1    jruoho 
    439   1.1    jruoho 	map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
    440   1.1    jruoho 	     fd, 0);
    441   1.1    jruoho 	ATF_REQUIRE(map != MAP_FAILED);
    442   1.1    jruoho 
    443   1.1    jruoho 	for (i = 0; i < page; i++)
    444   1.1    jruoho 		map[i] = 'x';
    445   1.1    jruoho 
    446   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, 0) == 0);
    447   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, page / 8) == 0);
    448   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, page / 4) == 0);
    449   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, page / 2) == 0);
    450   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, page / 12) == 0);
    451   1.1    jruoho 	ATF_REQUIRE(ftruncate(fd, page / 64) == 0);
    452   1.1    jruoho 
    453  1.11  christos 	(void)munmap(map, page);
    454   1.1    jruoho 	ATF_REQUIRE(close(fd) == 0);
    455   1.1    jruoho }
    456   1.1    jruoho 
    457   1.1    jruoho ATF_TC_CLEANUP(mmap_truncate, tc)
    458   1.1    jruoho {
    459   1.1    jruoho 	(void)unlink(path);
    460   1.1    jruoho }
    461   1.1    jruoho 
    462   1.8  christos ATF_TC_WITH_CLEANUP(mmap_truncate_signal);
    463   1.8  christos ATF_TC_HEAD(mmap_truncate_signal, tc)
    464   1.8  christos {
    465   1.8  christos 	atf_tc_set_md_var(tc, "descr",
    466   1.8  christos 	    "Test mmap(2) ftruncate(2) causing signal");
    467   1.8  christos }
    468   1.8  christos 
    469   1.8  christos ATF_TC_BODY(mmap_truncate_signal, tc)
    470   1.8  christos {
    471   1.8  christos 	char *map;
    472   1.8  christos 	long i;
    473   1.8  christos 	int fd, sta;
    474   1.8  christos 	pid_t pid;
    475   1.8  christos 
    476   1.8  christos 	fd = open(path, O_RDWR | O_CREAT, 0700);
    477   1.8  christos 
    478   1.8  christos 	if (fd < 0)
    479   1.8  christos 		return;
    480   1.8  christos 
    481   1.8  christos 	ATF_REQUIRE(write(fd, "foo\n", 5) == 5);
    482   1.8  christos 
    483   1.8  christos 	map = mmap(NULL, page, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
    484   1.8  christos 	ATF_REQUIRE(map != MAP_FAILED);
    485   1.8  christos 
    486   1.8  christos 	sta = 0;
    487   1.8  christos 	for (i = 0; i < 5; i++)
    488   1.8  christos 		sta += map[i];
    489   1.8  christos 	ATF_REQUIRE(sta == 334);
    490   1.8  christos 
    491   1.8  christos 	ATF_REQUIRE(ftruncate(fd, 0) == 0);
    492   1.8  christos 	pid = fork();
    493   1.8  christos 	ATF_REQUIRE(pid >= 0);
    494   1.8  christos 
    495   1.8  christos 	if (pid == 0) {
    496   1.8  christos 		ATF_REQUIRE(signal(SIGBUS, map_sighandler) != SIG_ERR);
    497   1.9    martin 		ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
    498   1.8  christos 		sta = 0;
    499   1.8  christos 		for (i = 0; i < page; i++)
    500   1.8  christos 			sta += map[i];
    501   1.9    martin 		/* child never will get this far, but the compiler will
    502   1.9    martin 		   not know, so better use the values calculated to
    503   1.9    martin 		   prevent the access to be optimized out */
    504   1.8  christos 		ATF_REQUIRE(i == 0);
    505   1.9    martin 		ATF_REQUIRE(sta == 0);
    506  1.11  christos 		(void)munmap(map, page);
    507  1.11  christos 		(void)close(fd);
    508   1.9    martin 		return;
    509   1.8  christos 	}
    510   1.8  christos 
    511   1.8  christos 	(void)wait(&sta);
    512   1.8  christos 
    513   1.8  christos 	ATF_REQUIRE(WIFEXITED(sta) != 0);
    514   1.9    martin 	if (WEXITSTATUS(sta) == SIGSEGV)
    515   1.9    martin 		atf_tc_fail("child process got SIGSEGV instead of SIGBUS");
    516   1.8  christos 	ATF_REQUIRE(WEXITSTATUS(sta) == SIGBUS);
    517   1.8  christos 	ATF_REQUIRE(munmap(map, page) == 0);
    518   1.8  christos 	ATF_REQUIRE(close(fd) == 0);
    519   1.8  christos }
    520   1.8  christos 
    521   1.8  christos ATF_TC_CLEANUP(mmap_truncate_signal, tc)
    522   1.8  christos {
    523   1.8  christos 	(void)unlink(path);
    524   1.8  christos }
    525   1.8  christos 
    526   1.1    jruoho ATF_TC(mmap_va0);
    527   1.1    jruoho ATF_TC_HEAD(mmap_va0, tc)
    528   1.1    jruoho {
    529   1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable");
    530   1.1    jruoho }
    531   1.1    jruoho 
    532   1.1    jruoho ATF_TC_BODY(mmap_va0, tc)
    533   1.1    jruoho {
    534   1.1    jruoho 	int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE;
    535   1.1    jruoho 	size_t len = sizeof(int);
    536   1.1    jruoho 	void *map;
    537   1.1    jruoho 	int val;
    538   1.1    jruoho 
    539   1.1    jruoho 	/*
    540   1.1    jruoho 	 * Make an anonymous fixed mapping at zero address. If the address
    541   1.1    jruoho 	 * is restricted as noted in security(7), the syscall should fail.
    542   1.1    jruoho 	 */
    543   1.1    jruoho 	if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0)
    544   1.1    jruoho 		atf_tc_fail("failed to read vm.user_va0_disable");
    545   1.1    jruoho 
    546   1.1    jruoho 	map = mmap(NULL, page, PROT_EXEC, 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, flags, -1, 0);
    550   1.1    jruoho 	map_check(map, val);
    551   1.1    jruoho 
    552   1.1    jruoho 	map = mmap(NULL, page, PROT_WRITE, flags, -1, 0);
    553   1.1    jruoho 	map_check(map, val);
    554   1.1    jruoho 
    555   1.1    jruoho 	map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0);
    556   1.1    jruoho 	map_check(map, val);
    557   1.1    jruoho 
    558   1.1    jruoho 	map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0);
    559   1.1    jruoho 	map_check(map, val);
    560   1.1    jruoho }
    561   1.1    jruoho 
    562   1.1    jruoho ATF_TP_ADD_TCS(tp)
    563   1.1    jruoho {
    564   1.1    jruoho 	page = sysconf(_SC_PAGESIZE);
    565   1.1    jruoho 	ATF_REQUIRE(page >= 0);
    566   1.1    jruoho 
    567   1.3    jruoho 	ATF_TP_ADD_TC(tp, mmap_block);
    568   1.1    jruoho 	ATF_TP_ADD_TC(tp, mmap_err);
    569   1.2    jruoho 	ATF_TP_ADD_TC(tp, mmap_loan);
    570   1.1    jruoho 	ATF_TP_ADD_TC(tp, mmap_prot_1);
    571   1.1    jruoho 	ATF_TP_ADD_TC(tp, mmap_prot_2);
    572   1.1    jruoho 	ATF_TP_ADD_TC(tp, mmap_prot_3);
    573   1.1    jruoho 	ATF_TP_ADD_TC(tp, mmap_truncate);
    574   1.8  christos 	ATF_TP_ADD_TC(tp, mmap_truncate_signal);
    575   1.1    jruoho 	ATF_TP_ADD_TC(tp, mmap_va0);
    576   1.1    jruoho 
    577   1.1    jruoho 	return atf_no_error();
    578   1.1    jruoho }
    579