• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) International Business Machines  Corp., 2001
3  *
4  * This program is free software;  you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program;  if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * NAME
21  *	mprotect03.c
22  *
23  * DESCRIPTION
24  *	Testcase to check the mprotect(2) system call.
25  *
26  * ALGORITHM
27  *	Create a shared mapped file region with PROT_READ | PROT_WRITE
28  *	using the mmap(2) call. Then, use mprotect(2) to disable the
29  *	write permission on the mapped region. Then, attempt to write to
30  *	the mapped region using memcpy(). This would generate a sigsegv.
31  *	Since the sigsegv is generated, this needs to be done in a child
32  *	process (as sigsegv would repeatedly be generated). The testcase
33  *	succeeds only when this sigsegv is generated while attempting to
34  *	memcpy() on a shared region with only read permission.
35  *
36  * HISTORY
37  *	07/2001 Ported by Wayne Boyer
38  *      05/2002 changed over to use tst_sig instead of sigaction
39  */
40 
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <sys/mman.h>
44 #include <limits.h>
45 #include <signal.h>
46 #include <sys/wait.h>
47 #include "test.h"
48 
49 #include "safe_macros.h"
50 
51 #ifndef PAGESIZE
52 #define PAGESIZE 4096
53 #endif
54 #define FAILED 1
55 
56 static void cleanup(void);
57 static void setup(void);
58 
59 char *TCID = "mprotect03";
60 int TST_TOTAL = 1;
61 int status;
62 char file1[BUFSIZ];
63 
main(int ac,char ** av)64 int main(int ac, char **av)
65 {
66 	int lc;
67 
68 	char *addr;
69 	int fd, pid;
70 	char *buf = "abcdefghijklmnopqrstuvwxyz";
71 
72 	tst_parse_opts(ac, av, NULL, NULL);
73 
74 	setup();
75 
76 	for (lc = 0; TEST_LOOPING(lc); lc++) {
77 		tst_count = 0;
78 
79 		if ((fd = open(file1, O_RDWR | O_CREAT, 0777)) < 0)
80 			tst_brkm(TBROK, cleanup, "open failed");
81 
82 		SAFE_WRITE(cleanup, 1, fd, buf, strlen(buf));
83 
84 		/*
85 		 * mmap the PAGESIZE bytes as read only.
86 		 */
87 		addr = mmap(0, strlen(buf), PROT_READ | PROT_WRITE, MAP_SHARED,
88 			    fd, 0);
89 		if (addr == MAP_FAILED)
90 			tst_brkm(TBROK, cleanup, "mmap failed");
91 
92 		/*
93 		 * Try to change the protection to WRITE.
94 		 */
95 		TEST(mprotect(addr, strlen(buf), PROT_READ));
96 
97 		if (TEST_RETURN != -1) {
98 			if ((pid = FORK_OR_VFORK()) == -1) {
99 				tst_brkm(TBROK, cleanup, "fork failed");
100 			}
101 
102 			if (pid == 0) {
103 				memcpy(addr, buf, strlen(buf));
104 				tst_resm(TINFO, "memcpy() did "
105 					 "not generate SIGSEGV");
106 				exit(1);
107 			}
108 
109 			waitpid(pid, &status, 0);
110 			if (WEXITSTATUS(status) != 0) {
111 				tst_resm(TFAIL, "child returned "
112 					 "unexpected status");
113 			} else {
114 				tst_resm(TPASS, "SIGSEGV generated "
115 					 "as expected");
116 			}
117 		} else {
118 			tst_resm(TFAIL, "mprotect failed "
119 				 "unexpectedly, errno: %d", errno);
120 		}
121 
122 		/* clean up things in case we are looping */
123 		SAFE_MUNMAP(cleanup, addr, strlen(buf));
124 		SAFE_CLOSE(cleanup, fd);
125 		SAFE_UNLINK(cleanup, file1);
126 	}
127 
128 	cleanup();
129 	tst_exit();
130 }
131 
sighandler(int sig)132 static void sighandler(int sig)
133 {
134 	if (sig == SIGSEGV) {
135 		tst_resm(TINFO, "received signal: SIGSEGV");
136 		tst_exit();
137 	} else
138 		tst_brkm(TBROK, 0, "Unexpected signal %d received.", sig);
139 }
140 
setup(void)141 static void setup(void)
142 {
143 	tst_sig(FORK, sighandler, NULL);
144 
145 	TEST_PAUSE;
146 
147 	tst_tmpdir();
148 
149 	sprintf(file1, "mprotect03.tmp.%d", getpid());
150 }
151 
cleanup(void)152 static void cleanup(void)
153 {
154 	tst_rmdir();
155 }
156