1178825Sdfr/* 2233294Sstas * Copyright (c) 1999 - 2004 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include <config.h> 35233294Sstas 36178825Sdfr#ifdef HAVE_SYS_MMAN_H 37178825Sdfr#include <sys/mman.h> 38178825Sdfr#endif 39178825Sdfr#include <stdio.h> 40178825Sdfr#include <string.h> 41178825Sdfr#include <err.h> 42178825Sdfr#include "roken.h" 43178825Sdfr 44178825Sdfr#include "test-mem.h" 45178825Sdfr 46178825Sdfr/* #undef HAVE_MMAP */ 47178825Sdfr 48178825Sdfrstruct { 49178825Sdfr void *start; 50178825Sdfr size_t size; 51178825Sdfr void *data_start; 52178825Sdfr size_t data_size; 53178825Sdfr enum rk_test_mem_type type; 54178825Sdfr int fd; 55178825Sdfr} map; 56178825Sdfr 57233294Sstas#ifdef HAVE_SIGACTION 58233294Sstas 59178825Sdfrstruct sigaction sa, osa; 60178825Sdfr 61233294Sstas#else 62233294Sstas 63233294Sstasvoid (* osigh)(int); 64233294Sstas 65233294Sstas#endif 66233294Sstas 67178825Sdfrchar *testname; 68178825Sdfr 69178825Sdfrstatic RETSIGTYPE 70178825Sdfrsegv_handler(int sig) 71178825Sdfr{ 72178825Sdfr int fd; 73178825Sdfr char msg[] = "SIGSEGV i current test: "; 74233294Sstas 75178825Sdfr fd = open("/dev/stdout", O_WRONLY, 0600); 76178825Sdfr if (fd >= 0) { 77233294Sstas (void)write(fd, msg, sizeof(msg) - 1); 78233294Sstas (void)write(fd, testname, strlen(testname)); 79233294Sstas (void)write(fd, "\n", 1); 80178825Sdfr close(fd); 81178825Sdfr } 82178825Sdfr _exit(1); 83178825Sdfr} 84178825Sdfr 85178825Sdfr#define TESTREC() \ 86178825Sdfr if (testname) \ 87178825Sdfr errx(1, "test %s run recursively on %s", name, testname); \ 88178825Sdfr testname = strdup(name); \ 89178825Sdfr if (testname == NULL) \ 90178825Sdfr errx(1, "malloc"); 91178825Sdfr 92178825Sdfr 93233294SstasROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL 94178825Sdfrrk_test_mem_alloc(enum rk_test_mem_type type, const char *name, 95178825Sdfr void *buf, size_t size) 96178825Sdfr{ 97178825Sdfr#ifndef HAVE_MMAP 98178825Sdfr unsigned char *p; 99233294Sstas 100178825Sdfr TESTREC(); 101178825Sdfr 102178825Sdfr p = malloc(size + 2); 103178825Sdfr if (p == NULL) 104178825Sdfr errx(1, "malloc"); 105178825Sdfr map.type = type; 106178825Sdfr map.start = p; 107178825Sdfr map.size = size + 2; 108178825Sdfr p[0] = 0xff; 109233294Sstas p[map.size-1] = 0xff; 110178825Sdfr map.data_start = p + 1; 111178825Sdfr#else 112178825Sdfr unsigned char *p; 113178825Sdfr int flags, ret, fd; 114178825Sdfr size_t pagesize = getpagesize(); 115178825Sdfr 116178825Sdfr TESTREC(); 117178825Sdfr 118178825Sdfr map.type = type; 119178825Sdfr 120178825Sdfr#ifdef MAP_ANON 121178825Sdfr flags = MAP_ANON; 122178825Sdfr fd = -1; 123178825Sdfr#else 124178825Sdfr flags = 0; 125178825Sdfr fd = open ("/dev/zero", O_RDONLY); 126178825Sdfr if(fd < 0) 127178825Sdfr err (1, "open /dev/zero"); 128178825Sdfr#endif 129178825Sdfr map.fd = fd; 130178825Sdfr flags |= MAP_PRIVATE; 131178825Sdfr 132178825Sdfr map.size = size + pagesize - (size % pagesize) + pagesize * 2; 133178825Sdfr 134178825Sdfr p = (unsigned char *)mmap(0, map.size, PROT_READ | PROT_WRITE, 135178825Sdfr flags, fd, 0); 136178825Sdfr if (p == (unsigned char *)MAP_FAILED) 137178825Sdfr err (1, "mmap"); 138178825Sdfr 139178825Sdfr map.start = p; 140178825Sdfr 141178825Sdfr ret = mprotect ((void *)p, pagesize, 0); 142178825Sdfr if (ret < 0) 143178825Sdfr err (1, "mprotect"); 144178825Sdfr 145178825Sdfr ret = mprotect (p + map.size - pagesize, pagesize, 0); 146178825Sdfr if (ret < 0) 147178825Sdfr err (1, "mprotect"); 148178825Sdfr 149178825Sdfr switch (type) { 150178825Sdfr case RK_TM_OVERRUN: 151178825Sdfr map.data_start = p + map.size - pagesize - size; 152178825Sdfr break; 153178825Sdfr case RK_TM_UNDERRUN: 154178825Sdfr map.data_start = p + pagesize; 155178825Sdfr break; 156178825Sdfr default: 157178825Sdfr abort(); 158178825Sdfr } 159178825Sdfr#endif 160233294Sstas#ifdef HAVE_SIGACTION 161178825Sdfr sigemptyset (&sa.sa_mask); 162178825Sdfr sa.sa_flags = 0; 163178825Sdfr#ifdef SA_RESETHAND 164178825Sdfr sa.sa_flags |= SA_RESETHAND; 165178825Sdfr#endif 166178825Sdfr sa.sa_handler = segv_handler; 167178825Sdfr sigaction (SIGSEGV, &sa, &osa); 168233294Sstas#else 169233294Sstas osigh = signal(SIGSEGV, segv_handler); 170233294Sstas#endif 171178825Sdfr 172178825Sdfr map.data_size = size; 173178825Sdfr if (buf) 174178825Sdfr memcpy(map.data_start, buf, size); 175178825Sdfr return map.data_start; 176178825Sdfr} 177178825Sdfr 178233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 179178825Sdfrrk_test_mem_free(const char *map_name) 180178825Sdfr{ 181178825Sdfr#ifndef HAVE_MMAP 182178825Sdfr unsigned char *p = map.start; 183233294Sstas 184178825Sdfr if (testname == NULL) 185178825Sdfr errx(1, "test_mem_free call on no free"); 186178825Sdfr 187178825Sdfr if (p[0] != 0xff) 188178825Sdfr errx(1, "%s: %s underrun %x\n", testname, map_name, p[0]); 189233294Sstas if (p[map.size-1] != 0xff) 190178825Sdfr errx(1, "%s: %s overrun %x\n", testname, map_name, p[map.size - 1]); 191178825Sdfr free(map.start); 192178825Sdfr#else 193178825Sdfr int ret; 194233294Sstas 195178825Sdfr if (testname == NULL) 196178825Sdfr errx(1, "test_mem_free call on no free"); 197178825Sdfr 198178825Sdfr ret = munmap (map.start, map.size); 199178825Sdfr if (ret < 0) 200178825Sdfr err (1, "munmap"); 201178825Sdfr if (map.fd > 0) 202178825Sdfr close(map.fd); 203178825Sdfr#endif 204178825Sdfr free(testname); 205178825Sdfr testname = NULL; 206178825Sdfr 207233294Sstas#ifdef HAVE_SIGACTION 208178825Sdfr sigaction (SIGSEGV, &osa, NULL); 209233294Sstas#else 210233294Sstas signal (SIGSEGV, osigh); 211233294Sstas#endif 212178825Sdfr} 213