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