1/* $NetBSD$ */ 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 50struct { 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 61struct sigaction sa, osa; 62 63#else 64 65void (* osigh)(int); 66 67#endif 68 69char *testname; 70 71static RETSIGTYPE 72segv_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 95ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL 96rk_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 180ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 181rk_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