1 /* 2 * Copyright (c) 1999 - 2004 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifdef HAVE_CONFIG_H 35 #include <config.h> 36 #endif 37 #ifdef HAVE_SYS_MMAN_H 38 #include <sys/mman.h> 39 #endif 40 #include <stdio.h> 41 #include <string.h> 42 #include <err.h> 43 #include "roken.h" 44 45 #include "test-mem.h" 46 47 RCSID("$Id: test-mem.c 21005 2007-06-08 01:54:35Z lha $"); 48 49 /* #undef HAVE_MMAP */ 50 51 struct { 52 void *start; 53 size_t size; 54 void *data_start; 55 size_t data_size; 56 enum rk_test_mem_type type; 57 int fd; 58 } map; 59 60 struct sigaction sa, osa; 61 62 char *testname; 63 64 static RETSIGTYPE 65 segv_handler(int sig) 66 { 67 int fd; 68 char msg[] = "SIGSEGV i current test: "; 69 70 fd = open("/dev/stdout", O_WRONLY, 0600); 71 if (fd >= 0) { 72 write(fd, msg, sizeof(msg) - 1); 73 write(fd, testname, strlen(testname)); 74 write(fd, "\n", 1); 75 close(fd); 76 } 77 _exit(1); 78 } 79 80 #define TESTREC() \ 81 if (testname) \ 82 errx(1, "test %s run recursively on %s", name, testname); \ 83 testname = strdup(name); \ 84 if (testname == NULL) \ 85 errx(1, "malloc"); 86 87 88 void * ROKEN_LIB_FUNCTION 89 rk_test_mem_alloc(enum rk_test_mem_type type, const char *name, 90 void *buf, size_t size) 91 { 92 #ifndef HAVE_MMAP 93 unsigned char *p; 94 95 TESTREC(); 96 97 p = malloc(size + 2); 98 if (p == NULL) 99 errx(1, "malloc"); 100 map.type = type; 101 map.start = p; 102 map.size = size + 2; 103 p[0] = 0xff; 104 p[map.size] = 0xff; 105 map.data_start = p + 1; 106 #else 107 unsigned char *p; 108 int flags, ret, fd; 109 size_t pagesize = getpagesize(); 110 111 TESTREC(); 112 113 map.type = type; 114 115 #ifdef MAP_ANON 116 flags = MAP_ANON; 117 fd = -1; 118 #else 119 flags = 0; 120 fd = open ("/dev/zero", O_RDONLY); 121 if(fd < 0) 122 err (1, "open /dev/zero"); 123 #endif 124 map.fd = fd; 125 flags |= MAP_PRIVATE; 126 127 map.size = size + pagesize - (size % pagesize) + pagesize * 2; 128 129 p = (unsigned char *)mmap(0, map.size, PROT_READ | PROT_WRITE, 130 flags, fd, 0); 131 if (p == (unsigned char *)MAP_FAILED) 132 err (1, "mmap"); 133 134 map.start = p; 135 136 ret = mprotect ((void *)p, pagesize, 0); 137 if (ret < 0) 138 err (1, "mprotect"); 139 140 ret = mprotect (p + map.size - pagesize, pagesize, 0); 141 if (ret < 0) 142 err (1, "mprotect"); 143 144 switch (type) { 145 case RK_TM_OVERRUN: 146 map.data_start = p + map.size - pagesize - size; 147 break; 148 case RK_TM_UNDERRUN: 149 map.data_start = p + pagesize; 150 break; 151 default: 152 abort(); 153 } 154 #endif 155 sigemptyset (&sa.sa_mask); 156 sa.sa_flags = 0; 157 #ifdef SA_RESETHAND 158 sa.sa_flags |= SA_RESETHAND; 159 #endif 160 sa.sa_handler = segv_handler; 161 sigaction (SIGSEGV, &sa, &osa); 162 163 map.data_size = size; 164 if (buf) 165 memcpy(map.data_start, buf, size); 166 return map.data_start; 167 } 168 169 void ROKEN_LIB_FUNCTION 170 rk_test_mem_free(const char *map_name) 171 { 172 #ifndef HAVE_MMAP 173 unsigned char *p = map.start; 174 175 if (testname == NULL) 176 errx(1, "test_mem_free call on no free"); 177 178 if (p[0] != 0xff) 179 errx(1, "%s: %s underrun %x\n", testname, map_name, p[0]); 180 if (p[map.size] != 0xff) 181 errx(1, "%s: %s overrun %x\n", testname, map_name, p[map.size - 1]); 182 free(map.start); 183 #else 184 int ret; 185 186 if (testname == NULL) 187 errx(1, "test_mem_free call on no free"); 188 189 ret = munmap (map.start, map.size); 190 if (ret < 0) 191 err (1, "munmap"); 192 if (map.fd > 0) 193 close(map.fd); 194 #endif 195 free(testname); 196 testname = NULL; 197 198 sigaction (SIGSEGV, &osa, NULL); 199 } 200