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