Home | History | Annotate | Download | only in mprotect
      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 
     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 
    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 
    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 
    152 static void cleanup(void)
    153 {
    154 	tst_rmdir();
    155 }
    156