xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/roken/test-mem.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: test-mem.c,v 1.2 2017/01/28 21:31:50 christos 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
segv_handler(int sig)72 segv_handler(int sig)
73 {
74     int fd;
75     ssize_t ret;
76     char msg[] = "SIGSEGV i current test: ";
77 
78     fd = open("/dev/stdout", O_WRONLY, 0600);
79     if (fd >= 0) {
80 	ret = write(fd, msg, sizeof(msg) - 1);
81 	if (ret != -1)
82 	    ret = write(fd, testname, strlen(testname));
83 	if (ret != -1)
84 	    ret = write(fd, "\n", 1);
85 	close(fd);
86     }
87     _exit(1);
88 }
89 
90 #define TESTREC()							\
91     if (testname)							\
92 	errx(1, "test %s run recursively on %s", name, testname);	\
93     testname = strdup(name);						\
94     if (testname == NULL)						\
95 	errx(1, "malloc");
96 
97 
98 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)99 rk_test_mem_alloc(enum rk_test_mem_type type, const char *name,
100 		  void *buf, size_t size)
101 {
102 #ifndef HAVE_MMAP
103     unsigned char *p;
104 
105     TESTREC();
106 
107     p = malloc(size + 2);
108     if (p == NULL)
109 	errx(1, "malloc");
110     map.type = type;
111     map.start = p;
112     map.size = size + 2;
113     p[0] = 0xff;
114     p[map.size-1] = 0xff;
115     map.data_start = p + 1;
116 #else
117     unsigned char *p;
118     int flags, ret, fd;
119     size_t pagesize = getpagesize();
120 
121     TESTREC();
122 
123     map.type = type;
124 
125 #ifdef MAP_ANON
126     flags = MAP_ANON;
127     fd = -1;
128 #else
129     flags = 0;
130     fd = open ("/dev/zero", O_RDONLY);
131     if(fd < 0)
132 	err (1, "open /dev/zero");
133 #endif
134     map.fd = fd;
135     flags |= MAP_PRIVATE;
136 
137     map.size = size + pagesize - (size % pagesize) + pagesize * 2;
138 
139     p = (unsigned char *)mmap(0, map.size, PROT_READ | PROT_WRITE,
140 			      flags, fd, 0);
141     if (p == (unsigned char *)MAP_FAILED)
142 	err (1, "mmap");
143 
144     map.start = p;
145 
146     ret = mprotect ((void *)p, pagesize, 0);
147     if (ret < 0)
148 	err (1, "mprotect");
149 
150     ret = mprotect (p + map.size - pagesize, pagesize, 0);
151     if (ret < 0)
152 	err (1, "mprotect");
153 
154     switch (type) {
155     case RK_TM_OVERRUN:
156 	map.data_start = p + map.size - pagesize - size;
157 	break;
158     case RK_TM_UNDERRUN:
159 	map.data_start = p + pagesize;
160 	break;
161     default:
162 	abort();
163     }
164 #endif
165 #ifdef HAVE_SIGACTION
166     sigemptyset (&sa.sa_mask);
167     sa.sa_flags = 0;
168 #ifdef SA_RESETHAND
169     sa.sa_flags |= SA_RESETHAND;
170 #endif
171     sa.sa_handler = segv_handler;
172     sigaction (SIGSEGV, &sa, &osa);
173 #else
174     osigh = signal(SIGSEGV, segv_handler);
175 #endif
176 
177     map.data_size = size;
178     if (buf)
179 	memcpy(map.data_start, buf, size);
180     return map.data_start;
181 }
182 
183 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_test_mem_free(const char * map_name)184 rk_test_mem_free(const char *map_name)
185 {
186 #ifndef HAVE_MMAP
187     unsigned char *p = map.start;
188 
189     if (testname == NULL)
190 	errx(1, "test_mem_free call on no free");
191 
192     if (p[0] != 0xff)
193 	errx(1, "%s: %s underrun %x\n", testname, map_name, p[0]);
194     if (p[map.size-1] != 0xff)
195 	errx(1, "%s: %s overrun %x\n", testname, map_name, p[map.size - 1]);
196     free(map.start);
197 #else
198     int ret;
199 
200     if (testname == NULL)
201 	errx(1, "test_mem_free call on no free");
202 
203     ret = munmap (map.start, map.size);
204     if (ret < 0)
205 	err (1, "munmap");
206     if (map.fd > 0)
207 	close(map.fd);
208 #endif
209     free(testname);
210     testname = NULL;
211 
212 #ifdef HAVE_SIGACTION
213     sigaction (SIGSEGV, &osa, NULL);
214 #else
215     signal (SIGSEGV, osigh);
216 #endif
217 }
218