source: zzuf/trunk/src/load-mem.c @ 1644

Last change on this file since 1644 was 1644, checked in by Sam Hocevar, 14 years ago
  • Oops, fixed an old OS X build failure.
  • Property svn:keywords set to Id
File size: 9.2 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: load-mem.c 1644 2007-01-10 17:25:09Z 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 <dlfcn.h>
38#include <errno.h>
39#include <signal.h>
40
41#if defined HAVE_MALLOC_H
42#   include <malloc.h>
43#endif
44#include <unistd.h>
45#include <sys/mman.h>
46#if defined HAVE_LIBC_H
47#   include <libc.h>
48#endif
49
50#include "libzzuf.h"
51#include "debug.h"
52#include "fuzz.h"
53#include "load.h"
54#include "fd.h"
55
56/* Library functions that we divert */
57static void *  (*calloc_orig)   (size_t nmemb, size_t size);
58static void *  (*malloc_orig)   (size_t size);
59static void    (*free_orig)     (void *ptr);
60static void *  (*valloc_orig)   (size_t size);
61#ifdef HAVE_MEMALIGN
62static void *  (*memalign_orig) (size_t boundary, size_t size);
63#endif
64#ifdef HAVE_POSIX_MEMALIGN
65static int     (*posix_memalign_orig) (void **memptr, size_t alignment,
66                                       size_t size);
67#endif
68static void *  (*realloc_orig)  (void *ptr, size_t size);
69static int     (*brk_orig)      (void *end_data_segment);
70static void *  (*sbrk_orig)     (intptr_t increment);
71
72static void *  (*mmap_orig)     (void *start, size_t length, int prot,
73                                 int flags, int fd, off_t offset);
74/* TODO */
75/* static void *  (*mremap_orig)   (void *old_address, size_t old_size,
76                                 size_t new_size, int flags); */
77#ifdef HAVE_MMAP64
78static void *  (*mmap64_orig)   (void *start, size_t length, int prot,
79                                 int flags, int fd, off64_t offset);
80#endif
81static int     (*munmap_orig)   (void *start, size_t length);
82#ifdef HAVE_MAP_FD
83static kern_return_t (*map_fd_orig) (int fd, vm_offset_t offset,
84                                     vm_offset_t *addr, boolean_t find_space,
85                                     vm_size_t numbytes);
86#endif
87
88void _zz_load_mem(void)
89{
90    LOADSYM(calloc);
91    LOADSYM(malloc);
92    LOADSYM(free);
93    LOADSYM(realloc);
94    LOADSYM(valloc);
95#ifdef HAVE_MEMALIGN
96    LOADSYM(memalign);
97#endif
98#ifdef HAVE_POSIX_MEMALIGN
99    LOADSYM(posix_memalign);
100#endif
101    LOADSYM(brk);
102    LOADSYM(sbrk);
103
104    LOADSYM(mmap);
105#ifdef HAVE_MMAP64
106    LOADSYM(mmap64);
107#endif
108    LOADSYM(munmap);
109#ifdef HAVE_MAP_FD
110    LOADSYM(map_fd);
111#endif
112}
113
114/* 32k of ugly static memory for programs that call us *before* we’re
115 * initialised */
116uint64_t dummy_buffer[4096];
117
118void *calloc(size_t nmemb, size_t size)
119{
120    void *ret;
121    if(!_zz_ready)
122    {
123        /* Calloc says we must zero the data */
124        int i = (nmemb * size + 7) / 8;
125        while(i--)
126            dummy_buffer[i] = 0;
127        return dummy_buffer;
128    }
129    ret = calloc_orig(nmemb, size);
130    if(ret == NULL && _zz_memory && errno == ENOMEM)
131        raise(SIGKILL);
132    return ret;
133}
134
135void *malloc(size_t size)
136{
137    void *ret;
138    if(!_zz_ready)
139        return dummy_buffer;
140    ret = malloc_orig(size);
141    if(ret == NULL && _zz_memory && errno == ENOMEM)
142        raise(SIGKILL);
143    return ret;
144}
145
146void free(void *ptr)
147{
148    if(ptr == dummy_buffer)
149        return;
150    if(!_zz_ready)
151        LOADSYM(free);
152    free_orig(ptr);
153}
154
155void *realloc(void *ptr, size_t size)
156{
157    void *ret;
158    if(ptr == dummy_buffer)
159        return ptr;
160    if(!_zz_ready)
161        LOADSYM(realloc);
162    ret = realloc_orig(ptr, size);
163    if(ret == NULL && _zz_memory && errno == ENOMEM)
164        raise(SIGKILL);
165    return ret;
166}
167
168void *valloc(size_t size)
169{
170    void *ret;
171    if(!_zz_ready)
172        LOADSYM(valloc);
173    ret = valloc_orig(size);
174    if(ret == NULL && _zz_memory && errno == ENOMEM)
175        raise(SIGKILL);
176    return ret;
177}
178
179#ifdef HAVE_MEMALIGN
180void *memalign(size_t boundary, size_t size)
181{
182    void *ret;
183    if(!_zz_ready)
184        LOADSYM(memalign);
185    ret = memalign_orig(boundary, size);
186    if(ret == NULL && _zz_memory && errno == ENOMEM)
187        raise(SIGKILL);
188    return ret;
189}
190#endif
191
192#ifdef HAVE_POSIX_MEMALIGN
193int posix_memalign(void **memptr, size_t alignment, size_t size)
194{
195    int ret;
196    if(!_zz_ready)
197        LOADSYM(posix_memalign);
198    ret = posix_memalign_orig(memptr, alignment, size);
199    if(ret == ENOMEM && _zz_memory)
200        raise(SIGKILL);
201    return ret;
202}
203#endif
204
205int brk(void *end_data_segment)
206{
207    int ret;
208    if(!_zz_ready)
209        LOADSYM(brk);
210    ret = brk_orig(end_data_segment);
211    if(ret == -1 && _zz_memory && errno == ENOMEM)
212        raise(SIGKILL);
213    return ret;
214}
215
216void *sbrk(intptr_t increment)
217{
218    void *ret;
219    if(!_zz_ready)
220        LOADSYM(sbrk);
221    ret = sbrk_orig(increment);
222    if(ret == (void *)-1 && _zz_memory && errno == ENOMEM)
223        raise(SIGKILL);
224    return ret;
225}
226
227/* Table used for mmap() and munmap() */
228void **maps = NULL;
229int nbmaps = 0;
230
231#define MMAP(fn, off_t) \
232    do { \
233        if(!_zz_ready) \
234            LOADSYM(fn); \
235        ret = ORIG(fn)(start, length, prot, flags, fd, offset); \
236        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
237            return ret; \
238        if(ret && length) \
239        { \
240            char *b = malloc(length); \
241            int i, oldpos; \
242            for(i = 0; i < nbmaps; i += 2) \
243                if(maps[i] == NULL) \
244                    break; \
245            if(i == nbmaps) \
246            { \
247                nbmaps += 2; \
248                maps = realloc(maps, nbmaps * sizeof(void *)); \
249            } \
250            maps[i] = b; \
251            maps[i + 1] = ret; \
252            oldpos = _zz_getpos(fd); \
253            _zz_setpos(fd, offset); /* mmap() maps the fd at offset 0 */ \
254            memcpy(b, ret, length); /* FIXME: get rid of this */ \
255            _zz_fuzz(fd, (uint8_t *)b, length); \
256            _zz_setpos(fd, oldpos); \
257            ret = b; \
258            if(length >= 4) \
259                debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p \"%c%c%c%c...", \
260                      start, (long int)length, prot, flags, fd, \
261                      (long long int)offset, ret, b[0], b[1], b[2], b[3]); \
262            else \
263                debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p \"%c...", \
264                      start, (long int)length, prot, flags, fd, \
265                      (long long int)offset, ret, b[0]); \
266        } \
267        else \
268            debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p", \
269                  start, (long int)length, prot, flags, fd, \
270                  (long long int)offset, ret); \
271    } while(0)
272
273void *mmap(void *start, size_t length, int prot, int flags,
274           int fd, off_t offset)
275{
276    void *ret; MMAP(mmap, off_t); return ret;
277}
278
279#ifdef HAVE_MMAP64
280void *mmap64(void *start, size_t length, int prot, int flags,
281             int fd, off64_t offset)
282{
283    void *ret; MMAP(mmap64, off64_t); return ret;
284}
285#endif
286
287int munmap(void *start, size_t length)
288{
289    int ret, i;
290
291    if(!_zz_ready)
292        LOADSYM(munmap);
293    for(i = 0; i < nbmaps; i++)
294    {
295        if(maps[i] != start)
296            continue;
297
298        free(start);
299        ret = munmap_orig(maps[i + 1], length);
300        maps[i] = NULL;
301        maps[i + 1] = NULL;
302        debug("munmap(%p, %li) = %i", start, (long int)length, ret);
303        return ret;
304    }
305
306    return munmap_orig(start, length);
307}
308
309#ifdef HAVE_MAP_FD
310kern_return_t map_fd(int fd, vm_offset_t offset, vm_offset_t *addr,
311                     boolean_t find_space, vm_size_t numbytes)
312{
313    kern_return_t ret;
314
315    if(!_zz_ready)
316        LOADSYM(map_fd);
317    ret = map_fd_orig(fd, offset, addr, find_space, numbytes);
318    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
319        return ret;
320
321    if(ret == 0 && numbytes)
322    {
323        /* FIXME: do we also have to rewind the filedescriptor like in mmap? */
324        char *b = malloc(numbytes);
325        memcpy(b, (void *)*addr, numbytes);
326        _zz_fuzz(fd, (void *)b, numbytes);
327        *addr = (vm_offset_t)b;
328        /* FIXME: the map is never freed; there is no such thing as unmap_fd,
329         * but I suppose that kind of map should go when the filedescriptor is
330         * closed (unlike mmap, which returns a persistent buffer). */
331
332        if(numbytes >= 4)
333           debug("map_fd(%i, %lli, &%p, %i, %lli) = %i \"%c%c%c%c", fd,
334                 (long long int)offset, (void *)*addr, (int)find_space,
335                 (long long int)numbytes, ret, b[0], b[1], b[2], b[3]);
336        else
337           debug("map_fd(%i, %lli, &%p, %i, %lli) = %i \"%c", fd,
338                 (long long int)offset, (void *)*addr, (int)find_space,
339                 (long long int)numbytes, ret, b[0]);
340    }
341    else
342        debug("map_fd(%i, %lli, &%p, %i, %lli) = %i", fd, (long long int)offset,
343              (void *)*addr, (int)find_space, (long long int)numbytes, ret);
344
345    return ret;
346}
347#endif
348
Note: See TracBrowser for help on using the repository browser.