1 /*
2  * t_mmap_madvise_1.c
3  *
4  * Check that an mprotect(PROT_NONE) region cannot be read even after an
5  * madvise(MADV_WILLNEED) has been executed on the region.
6  *
7  * Returns 0 if mprotect() protected the segment, 1 if the segment was readable
8  * despite PROT_NONE.
9  *
10  * $Id: t_mmap_madvise_1.c,v 1.1 2011/10/30 15:10:34 me Exp me $
11  */
12 
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <sys/mman.h>
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <err.h>
24 
25 int
26 main(int argc, char *argv[])
27 {
28 	int fd;
29 	char *mem;
30 	char *tmpfile;
31 	char teststring[] = "hello, world!\0";
32 	int rc;
33 	char c0;
34 	int status;
35 
36 	/* Setup: create a test file, write a test pattern, map it */
37 	tmpfile = tmpnam(NULL);
38 
39 	fd = open(tmpfile, O_RDWR | O_CREAT | O_TRUNC, 0777);
40 	if (fd == -1)
41 		err(1, "open/creat failure");
42 
43 	unlink(tmpfile);
44 	write(fd, teststring, strlen(teststring));
45 	fsync(fd);
46 
47 	mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
48 	if (mem == MAP_FAILED)
49 		err(1, "mmap failure");
50 
51 	/* At this point the segment should be readable and reflect the file */
52 	rc = strcmp(mem, teststring);
53 	if (rc != 0)
54 		err(1, "unexpected map region");
55 
56 	rc = mprotect(mem, 4096, PROT_NONE);
57 	if (rc == -1)
58 		err(1, "mprotect error");
59 
60 	/* At this point the segment should no longer be readable */
61 
62 	/* POSIX hat: this call might want to fail w/ EINVAL; we are offering
63 	 * advice for a region that is invalid, posix_madvise() is marked as
64 	 * failing w/ EINVAL if "The value of advice is invalid." ; we need
65 	 * a more precise definition of invalid. */
66 	rc = madvise(mem, 4096, MADV_WILLNEED);
67 	if (rc == -1)
68 		err(1, "madvise failed");
69 
70 	/* Segment should still not be readable */
71 
72 	rc = fork();
73 	if (rc == 0) {
74 		c0 = mem[0];
75 		if (c0 == 'h')
76 			exit(0);
77 		exit(1);
78 	}
79 	wait(&status);
80 	rc = 0;
81 
82 	/* The child was able to read the segment. Uhoh. */
83 	if (WIFEXITED(status)) {
84 		rc = -1;
85 	}
86 	/* Child died via a signal (SEGV) */
87 	if (WIFSIGNALED(status)) {
88 		rc = 0;
89 	}
90 
91 	munmap(mem, 4096);
92 	close(fd);
93 
94 	printf("%d \n", rc);
95 	return (rc);
96 }
97 
98