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 * DESCRIPTION 21 * Testcase to check the error conditions for mprotect(2) 22 * 23 * ALGORITHM 24 * test1: 25 * Invoke mprotect() with an address of 0. Check if error 26 * is set to ENOMEM. 27 * test2: 28 * Invoke mprotect() with an address that is not a multiple 29 * of PAGESIZE. EINVAL 30 * test3: 31 * Mmap a file with only read permission (PROT_READ). 32 * Try to set write permission (PROT_WRITE) using mprotect(2). 33 * Check that error is set to EACCES. 34 * 35 * HISTORY 36 * 07/2001 Ported by Wayne Boyer 37 * 03/2002 Paul Larson: case 1 should expect ENOMEM not EFAULT 38 */ 39 40 #include <fcntl.h> 41 #include <errno.h> 42 #include <sys/mman.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include "test.h" 46 47 char *TCID = "mprotect01"; 48 int TST_TOTAL = 3; 49 50 struct test_case { 51 void *addr; 52 int len; 53 int prot; 54 int error; 55 void (*setupfunc) (struct test_case *self); 56 }; 57 58 static void cleanup(void); 59 static void setup(void); 60 static void setup1(struct test_case *self); 61 static void setup2(struct test_case *self); 62 static void setup3(struct test_case *self); 63 64 static int fd; 65 66 struct test_case TC[] = { 67 /* Check for ENOMEM passing memory that cannot be accessed. */ 68 {NULL, 0, PROT_READ, ENOMEM, setup1}, 69 70 /* 71 * Check for EINVAL by passing a pointer which is not a 72 * multiple of PAGESIZE. 73 */ 74 {NULL, 1024, PROT_READ, EINVAL, setup2}, 75 /* 76 * Check for EACCES by trying to mark a section of memory 77 * which has been mmap'ed as read-only, as PROT_WRITE 78 */ 79 {NULL, 0, PROT_WRITE, EACCES, setup3} 80 }; 81 82 int main(int ac, char **av) 83 { 84 int lc; 85 int i; 86 87 tst_parse_opts(ac, av, NULL, NULL); 88 89 setup(); 90 91 for (lc = 0; TEST_LOOPING(lc); lc++) { 92 tst_count = 0; 93 94 for (i = 0; i < TST_TOTAL; i++) { 95 96 if (TC[i].setupfunc != NULL) 97 TC[i].setupfunc(&TC[i]); 98 99 TEST(mprotect(TC[i].addr, TC[i].len, TC[i].prot)); 100 101 if (TEST_RETURN != -1) { 102 tst_resm(TFAIL, "call succeeded unexpectedly"); 103 continue; 104 } 105 106 if (TEST_ERRNO == TC[i].error) { 107 tst_resm(TPASS, "expected failure - " 108 "errno = %d : %s", TEST_ERRNO, 109 strerror(TEST_ERRNO)); 110 } else { 111 tst_resm(TFAIL, "unexpected error - %d : %s - " 112 "expected %d", TEST_ERRNO, 113 strerror(TEST_ERRNO), TC[i].error); 114 } 115 } 116 } 117 cleanup(); 118 tst_exit(); 119 } 120 121 static void setup1(struct test_case *self) 122 { 123 self->len = getpagesize() + 1; 124 } 125 126 static void setup2(struct test_case *self) 127 { 128 self->addr = malloc(getpagesize()); 129 130 if (self->addr == NULL) 131 tst_brkm(TINFO, cleanup, "malloc failed"); 132 133 /* Ensure addr2 is not page aligned */ 134 self->addr++; 135 } 136 137 static void setup3(struct test_case *self) 138 { 139 fd = open("/etc/passwd", O_RDONLY); 140 if (fd < 0) 141 tst_brkm(TBROK, cleanup, "open failed"); 142 143 self->len = getpagesize(); 144 145 /* 146 * mmap the PAGESIZE bytes as read only. 147 */ 148 self->addr = mmap(0, self->len, PROT_READ, MAP_SHARED, fd, 0); 149 if (self->addr == MAP_FAILED) 150 tst_brkm(TBROK, cleanup, "mmap failed"); 151 152 } 153 154 static void setup(void) 155 { 156 tst_sig(FORK, DEF_HANDLER, cleanup); 157 158 TEST_PAUSE; 159 } 160 161 static void cleanup(void) 162 { 163 close(fd); 164 } 165