xref: /dflybsd-src/test/testcases/mem/mmap_madvise_1/mmap_madvise_1.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * t_mmap_madvise_1.c
386d7f5d3SJohn Marino  *
486d7f5d3SJohn Marino  * Check that an mprotect(PROT_NONE) region cannot be read even after an
586d7f5d3SJohn Marino  * madvise(MADV_WILLNEED) has been executed on the region.
686d7f5d3SJohn Marino  *
786d7f5d3SJohn Marino  * Returns 0 if mprotect() protected the segment, 1 if the segment was readable
886d7f5d3SJohn Marino  * despite PROT_NONE.
986d7f5d3SJohn Marino  *
1086d7f5d3SJohn Marino  * $Id: t_mmap_madvise_1.c,v 1.1 2011/10/30 15:10:34 me Exp me $
1186d7f5d3SJohn Marino  */
1286d7f5d3SJohn Marino 
1386d7f5d3SJohn Marino #include <sys/types.h>
1486d7f5d3SJohn Marino #include <sys/wait.h>
1586d7f5d3SJohn Marino #include <sys/mman.h>
1686d7f5d3SJohn Marino 
1786d7f5d3SJohn Marino #include <stdio.h>
1886d7f5d3SJohn Marino #include <stdlib.h>
1986d7f5d3SJohn Marino #include <string.h>
2086d7f5d3SJohn Marino #include <errno.h>
2186d7f5d3SJohn Marino #include <fcntl.h>
2286d7f5d3SJohn Marino #include <unistd.h>
2386d7f5d3SJohn Marino #include <err.h>
2486d7f5d3SJohn Marino 
2586d7f5d3SJohn Marino int
main(int argc,char * argv[])2686d7f5d3SJohn Marino main(int argc, char *argv[])
2786d7f5d3SJohn Marino {
2886d7f5d3SJohn Marino 	int fd;
2986d7f5d3SJohn Marino 	char *mem;
3086d7f5d3SJohn Marino 	char *tmpfile;
3186d7f5d3SJohn Marino 	char teststring[] = "hello, world!\0";
3286d7f5d3SJohn Marino 	int rc;
3386d7f5d3SJohn Marino 	char c0;
3486d7f5d3SJohn Marino 	int status;
3586d7f5d3SJohn Marino 
3686d7f5d3SJohn Marino 	/* Setup: create a test file, write a test pattern, map it */
3786d7f5d3SJohn Marino 	tmpfile = tmpnam(NULL);
3886d7f5d3SJohn Marino 
3986d7f5d3SJohn Marino 	fd = open(tmpfile, O_RDWR | O_CREAT | O_TRUNC, 0777);
4086d7f5d3SJohn Marino 	if (fd == -1)
4186d7f5d3SJohn Marino 		err(1, "open/creat failure");
4286d7f5d3SJohn Marino 
4386d7f5d3SJohn Marino 	unlink(tmpfile);
4486d7f5d3SJohn Marino 	write(fd, teststring, strlen(teststring));
4586d7f5d3SJohn Marino 	fsync(fd);
4686d7f5d3SJohn Marino 
4786d7f5d3SJohn Marino 	mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
4886d7f5d3SJohn Marino 	if (mem == MAP_FAILED)
4986d7f5d3SJohn Marino 		err(1, "mmap failure");
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino 	/* At this point the segment should be readable and reflect the file */
5286d7f5d3SJohn Marino 	rc = strcmp(mem, teststring);
5386d7f5d3SJohn Marino 	if (rc != 0)
5486d7f5d3SJohn Marino 		err(1, "unexpected map region");
5586d7f5d3SJohn Marino 
5686d7f5d3SJohn Marino 	rc = mprotect(mem, 4096, PROT_NONE);
5786d7f5d3SJohn Marino 	if (rc == -1)
5886d7f5d3SJohn Marino 		err(1, "mprotect error");
5986d7f5d3SJohn Marino 
6086d7f5d3SJohn Marino 	/* At this point the segment should no longer be readable */
6186d7f5d3SJohn Marino 
6286d7f5d3SJohn Marino 	/* POSIX hat: this call might want to fail w/ EINVAL; we are offering
6386d7f5d3SJohn Marino 	 * advice for a region that is invalid, posix_madvise() is marked as
6486d7f5d3SJohn Marino 	 * failing w/ EINVAL if "The value of advice is invalid." ; we need
6586d7f5d3SJohn Marino 	 * a more precise definition of invalid. */
6686d7f5d3SJohn Marino 	rc = madvise(mem, 4096, MADV_WILLNEED);
6786d7f5d3SJohn Marino 	if (rc == -1)
6886d7f5d3SJohn Marino 		err(1, "madvise failed");
6986d7f5d3SJohn Marino 
7086d7f5d3SJohn Marino 	/* Segment should still not be readable */
7186d7f5d3SJohn Marino 
7286d7f5d3SJohn Marino 	rc = fork();
7386d7f5d3SJohn Marino 	if (rc == 0) {
7486d7f5d3SJohn Marino 		c0 = mem[0];
7586d7f5d3SJohn Marino 		if (c0 == 'h')
7686d7f5d3SJohn Marino 			exit(0);
7786d7f5d3SJohn Marino 		exit(1);
7886d7f5d3SJohn Marino 	}
7986d7f5d3SJohn Marino 	wait(&status);
8086d7f5d3SJohn Marino 	rc = 0;
8186d7f5d3SJohn Marino 
8286d7f5d3SJohn Marino 	/* The child was able to read the segment. Uhoh. */
8386d7f5d3SJohn Marino 	if (WIFEXITED(status)) {
8486d7f5d3SJohn Marino 		rc = -1;
8586d7f5d3SJohn Marino 	}
8686d7f5d3SJohn Marino 	/* Child died via a signal (SEGV) */
8786d7f5d3SJohn Marino 	if (WIFSIGNALED(status)) {
8886d7f5d3SJohn Marino 		rc = 0;
8986d7f5d3SJohn Marino 	}
9086d7f5d3SJohn Marino 
9186d7f5d3SJohn Marino 	munmap(mem, 4096);
9286d7f5d3SJohn Marino 	close(fd);
9386d7f5d3SJohn Marino 
9486d7f5d3SJohn Marino 	printf("%d \n", rc);
9586d7f5d3SJohn Marino 	return (rc);
9686d7f5d3SJohn Marino }
9786d7f5d3SJohn Marino 
98