source: zzuf/trunk/src/lib-mem.c @ 1716

Last change on this file since 1716 was 1716, checked in by Sam Hocevar, 13 years ago
  • Put a few debug messages in malloc-related functions when they use our custom buffer.
  • Property svn:keywords set to Id
File size: 9.4 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006,2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: lib-mem.c 1716 2007-01-25 21:43:37Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  load-mem.c: loaded memory handling functions
17 */
18
19#include "config.h"
20
21/* Need this for RTLD_NEXT */
22#define _GNU_SOURCE
23/* Use this to get mmap64() on glibc systems */
24#define _LARGEFILE64_SOURCE
25/* Use this to get posix_memalign */
26#if defined HAVE_POSIX_MEMALIGN
27#   define _XOPEN_SOURCE 600
28#endif
29
30#if defined HAVE_STDINT_H
31#   include <stdint.h>
32#elif defined HAVE_INTTYPES_H
33#   include <inttypes.h>
34#endif
35#include <stdlib.h>
36#include <string.h>
37#include <errno.h>
38#include <signal.h>
39
40#if defined HAVE_MALLOC_H
41#   include <malloc.h>
42#endif
43#include <unistd.h>
44#if defined HAVE_SYS_MMAN_H
45#   include <sys/mman.h>
46#endif
47#if defined HAVE_LIBC_H
48#   include <libc.h>
49#endif
50
51#include "libzzuf.h"
52#include "lib-load.h"
53#include "debug.h"
54#include "fuzz.h"
55#include "fd.h"
56
57#if !defined SIGKILL
58#   define SIGKILL 9
59#endif
60
61/* TODO: mremap, maybe brk/sbrk (haha) */
62
63/* Library functions that we divert */
64static void *  (*ORIG(calloc))   (size_t nmemb, size_t size);
65static void *  (*ORIG(malloc))   (size_t size);
66static void    (*ORIG(free))     (void *ptr);
67#if defined HAVE_VALLOC
68static void *  (*ORIG(valloc))   (size_t size);
69#endif
70#if defined HAVE_MEMALIGN
71static void *  (*ORIG(memalign)) (size_t boundary, size_t size);
72#endif
73#if defined HAVE_POSIX_MEMALIGN
74static int     (*ORIG(posix_memalign)) (void **memptr, size_t alignment,
75                                        size_t size);
76#endif
77static void *  (*ORIG(realloc))  (void *ptr, size_t size);
78
79#if defined HAVE_MMAP
80static void *  (*ORIG(mmap))     (void *start, size_t length, int prot,
81                                  int flags, int fd, off_t offset);
82#endif
83#if defined HAVE_MMAP64
84static void *  (*ORIG(mmap64))   (void *start, size_t length, int prot,
85                                  int flags, int fd, off64_t offset);
86#endif
87#if defined HAVE_MUNMAP
88static int     (*ORIG(munmap))   (void *start, size_t length);
89#endif
90#if defined HAVE_MAP_FD
91static kern_return_t (*ORIG(map_fd)) (int fd, vm_offset_t offset,
92                                      vm_offset_t *addr, boolean_t find_space,
93                                      vm_size_t numbytes);
94#endif
95
96/* We need a static memory buffer because some functions call memory
97 * allocation routines before our library is loaded. Hell, even dlsym()
98 * calls calloc(), so we need to do something about it */
99#define DUMMY_BYTES 655360 /* 640 kB ought to be enough for anybody */
100static uint64_t dummy_buffer[DUMMY_BYTES / 8];
101static int dummy_offset = 0;
102#define DUMMY_START ((uintptr_t)dummy_buffer)
103#define DUMMY_STOP ((uintptr_t)dummy_buffer + DUMMY_BYTES)
104
105void _zz_mem_init(void)
106{
107    LOADSYM(calloc);
108    LOADSYM(malloc);
109    LOADSYM(realloc);
110}
111
112void *NEW(calloc)(size_t nmemb, size_t size)
113{
114    void *ret;
115    if(!ORIG(calloc))
116    {
117        ret = dummy_buffer + dummy_offset;
118        memset(ret, 0, (nmemb * size + 7) / 8);
119        dummy_offset += (nmemb * size + 7) / 8;
120        debug("%s(%li, %li) = %p", __func__,
121              (long int)nmemb, (long int)size, ret);
122        return ret;
123    }
124    ret = ORIG(calloc)(nmemb, size);
125    if(ret == NULL && _zz_memory && errno == ENOMEM)
126        raise(SIGKILL);
127    return ret;
128}
129
130void *NEW(malloc)(size_t size)
131{
132    void *ret;
133    if(!ORIG(malloc))
134    {
135        ret = dummy_buffer + dummy_offset;
136        dummy_offset += (size + 7) / 8;
137        debug("%s(%li) = %p", __func__, (long int)size, ret);
138        return ret;
139    }
140    ret = ORIG(malloc)(size);
141    if(ret == NULL && _zz_memory && errno == ENOMEM)
142        raise(SIGKILL);
143    return ret;
144}
145
146void NEW(free)(void *ptr)
147{
148    if((uintptr_t)ptr >= DUMMY_START && (uintptr_t)ptr < DUMMY_STOP)
149    {
150        debug("%s(%p)", __func__, ptr);
151        return;
152    }
153    LOADSYM(free);
154    ORIG(free)(ptr);
155}
156
157void *NEW(realloc)(void *ptr, size_t size)
158{
159    void *ret;
160    if(!ORIG(realloc)
161        || ((uintptr_t)ptr >= DUMMY_START && (uintptr_t)ptr < DUMMY_STOP))
162    {
163        ret = dummy_buffer + dummy_offset;
164        memcpy(ret, ptr, size);
165        dummy_offset += (size + 7) * 8;
166        debug("%s(%p, %li) = %p", __func__, ptr, (long int)size, ret);
167        return ret;
168    }
169    LOADSYM(realloc);
170    ret = ORIG(realloc)(ptr, size);
171    if(ret == NULL && _zz_memory && errno == ENOMEM)
172        raise(SIGKILL);
173    return ret;
174}
175
176#if defined HAVE_VALLOC
177void *NEW(valloc)(size_t size)
178{
179    void *ret;
180    LOADSYM(valloc);
181    ret = ORIG(valloc)(size);
182    if(ret == NULL && _zz_memory && errno == ENOMEM)
183        raise(SIGKILL);
184    return ret;
185}
186#endif
187
188#if defined HAVE_MEMALIGN
189void *NEW(memalign)(size_t boundary, size_t size)
190{
191    void *ret;
192    LOADSYM(memalign);
193    ret = ORIG(memalign)(boundary, size);
194    if(ret == NULL && _zz_memory && errno == ENOMEM)
195        raise(SIGKILL);
196    return ret;
197}
198#endif
199
200#if defined HAVE_POSIX_MEMALIGN
201int NEW(posix_memalign)(void **memptr, size_t alignment, size_t size)
202{
203    int ret;
204    LOADSYM(posix_memalign);
205    ret = ORIG(posix_memalign)(memptr, alignment, size);
206    if(ret == ENOMEM && _zz_memory)
207        raise(SIGKILL);
208    return ret;
209}
210#endif
211
212/* Table used for mmap() and munmap() */
213void **maps = NULL;
214int nbmaps = 0;
215
216#define MMAP(fn, off_t) \
217    do { \
218        LOADSYM(fn); \
219        ret = ORIG(fn)(start, length, prot, flags, fd, offset); \
220        if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)) \
221            return ret; \
222        if(ret && length) \
223        { \
224            char *b = malloc(length); \
225            int i, oldpos; \
226            for(i = 0; i < nbmaps; i += 2) \
227                if(maps[i] == NULL) \
228                    break; \
229            if(i == nbmaps) \
230            { \
231                nbmaps += 2; \
232                maps = realloc(maps, nbmaps * sizeof(void *)); \
233            } \
234            maps[i] = b; \
235            maps[i + 1] = ret; \
236            oldpos = _zz_getpos(fd); \
237            _zz_setpos(fd, offset); /* mmap() maps the fd at offset 0 */ \
238            memcpy(b, ret, length); /* FIXME: get rid of this */ \
239            _zz_fuzz(fd, (uint8_t *)b, length); \
240            _zz_setpos(fd, oldpos); \
241            ret = b; \
242            if(length >= 4) \
243                debug("%s(%p, %li, %i, %i, %i, %lli) = %p \"%c%c%c%c...", \
244                      __func__, start, (long int)length, prot, flags, fd, \
245                      (long long int)offset, ret, b[0], b[1], b[2], b[3]); \
246            else \
247                debug("%s(%p, %li, %i, %i, %i, %lli) = %p \"%c...", \
248                      __func__, start, (long int)length, prot, flags, fd, \
249                      (long long int)offset, ret, b[0]); \
250        } \
251        else \
252            debug("%s(%p, %li, %i, %i, %i, %lli) = %p", \
253                  __func__, start, (long int)length, prot, flags, fd, \
254                  (long long int)offset, ret); \
255    } while(0)
256
257#if defined HAVE_MMAP
258void *NEW(mmap)(void *start, size_t length, int prot, int flags,
259                int fd, off_t offset)
260{
261    void *ret; MMAP(mmap, off_t); return ret;
262}
263#endif
264
265#if defined HAVE_MMAP64
266void *NEW(mmap64)(void *start, size_t length, int prot, int flags,
267                  int fd, off64_t offset)
268{
269    void *ret; MMAP(mmap64, off64_t); return ret;
270}
271#endif
272
273#if defined HAVE_MUNMAP
274int NEW(munmap)(void *start, size_t length)
275{
276    int ret, i;
277
278    LOADSYM(munmap);
279    for(i = 0; i < nbmaps; i++)
280    {
281        if(maps[i] != start)
282            continue;
283
284        free(start);
285        ret = ORIG(munmap)(maps[i + 1], length);
286        maps[i] = NULL;
287        maps[i + 1] = NULL;
288        debug("%s(%p, %li) = %i", __func__, start, (long int)length, ret);
289        return ret;
290    }
291
292    return ORIG(munmap)(start, length);
293}
294#endif
295
296#if defined HAVE_MAP_FD
297kern_return_t NEW(map_fd)(int fd, vm_offset_t offset, vm_offset_t *addr,
298                          boolean_t find_space, vm_size_t numbytes)
299{
300    kern_return_t ret;
301
302    LOADSYM(map_fd);
303    ret = ORIG(map_fd)(fd, offset, addr, find_space, numbytes);
304    if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
305        return ret;
306
307    if(ret == 0 && numbytes)
308    {
309        /* FIXME: do we also have to rewind the filedescriptor like in mmap? */
310        char *b = malloc(numbytes);
311        memcpy(b, (void *)*addr, numbytes);
312        _zz_fuzz(fd, (void *)b, numbytes);
313        *addr = (vm_offset_t)b;
314        /* FIXME: the map is never freed; there is no such thing as unmap_fd,
315         * but I suppose that kind of map should go when the filedescriptor is
316         * closed (unlike mmap, which returns a persistent buffer). */
317
318        if(numbytes >= 4)
319           debug("%s(%i, %lli, &%p, %i, %lli) = %i \"%c%c%c%c", __func__,
320                 fd, (long long int)offset, (void *)*addr, (int)find_space,
321                 (long long int)numbytes, ret, b[0], b[1], b[2], b[3]);
322        else
323           debug("%s(%i, %lli, &%p, %i, %lli) = %i \"%c", __func__, fd,
324                 (long long int)offset, (void *)*addr, (int)find_space,
325                 (long long int)numbytes, ret, b[0]);
326    }
327    else
328        debug("%s(%i, %lli, &%p, %i, %lli) = %i", __func__, fd,
329              (long long int)offset, (void *)*addr, (int)find_space,
330              (long long int)numbytes, ret);
331
332    return ret;
333}
334#endif
335
Note: See TracBrowser for help on using the repository browser.