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

Revision 1645, 8.5 KB checked in by sam, 6 years ago (diff)
  • Removed brk/sbrk, they're so outdated and useless.
  • Property svn:keywords set to Id
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006,2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
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/* TODO: mremap, maybe brk/sbrk */
57
58/* Library functions that we divert */
59static void *  (*calloc_orig)   (size_t nmemb, size_t size);
60static void *  (*malloc_orig)   (size_t size);
61static void    (*free_orig)     (void *ptr);
62static void *  (*valloc_orig)   (size_t size);
63#ifdef HAVE_MEMALIGN
64static void *  (*memalign_orig) (size_t boundary, size_t size);
65#endif
66#ifdef HAVE_POSIX_MEMALIGN
67static int     (*posix_memalign_orig) (void **memptr, size_t alignment,
68                                       size_t size);
69#endif
70static void *  (*realloc_orig)  (void *ptr, size_t size);
71
72static void *  (*mmap_orig)     (void *start, size_t length, int prot,
73                                 int flags, int fd, off_t offset);
74#ifdef HAVE_MMAP64
75static void *  (*mmap64_orig)   (void *start, size_t length, int prot,
76                                 int flags, int fd, off64_t offset);
77#endif
78static int     (*munmap_orig)   (void *start, size_t length);
79#ifdef HAVE_MAP_FD
80static kern_return_t (*map_fd_orig) (int fd, vm_offset_t offset,
81                                     vm_offset_t *addr, boolean_t find_space,
82                                     vm_size_t numbytes);
83#endif
84
85void _zz_load_mem(void)
86{
87    LOADSYM(calloc);
88    LOADSYM(malloc);
89    LOADSYM(free);
90    LOADSYM(realloc);
91    LOADSYM(valloc);
92#ifdef HAVE_MEMALIGN
93    LOADSYM(memalign);
94#endif
95#ifdef HAVE_POSIX_MEMALIGN
96    LOADSYM(posix_memalign);
97#endif
98
99    LOADSYM(mmap);
100#ifdef HAVE_MMAP64
101    LOADSYM(mmap64);
102#endif
103    LOADSYM(munmap);
104#ifdef HAVE_MAP_FD
105    LOADSYM(map_fd);
106#endif
107}
108
109/* 32k of ugly static memory for programs that call us *before* we’re
110 * initialised */
111uint64_t dummy_buffer[4096];
112
113void *calloc(size_t nmemb, size_t size)
114{
115    void *ret;
116    if(!_zz_ready)
117    {
118        /* Calloc says we must zero the data */
119        int i = (nmemb * size + 7) / 8;
120        while(i--)
121            dummy_buffer[i] = 0;
122        return dummy_buffer;
123    }
124    ret = calloc_orig(nmemb, size);
125    if(ret == NULL && _zz_memory && errno == ENOMEM)
126        raise(SIGKILL);
127    return ret;
128}
129
130void *malloc(size_t size)
131{
132    void *ret;
133    if(!_zz_ready)
134        return dummy_buffer;
135    ret = malloc_orig(size);
136    if(ret == NULL && _zz_memory && errno == ENOMEM)
137        raise(SIGKILL);
138    return ret;
139}
140
141void free(void *ptr)
142{
143    if(ptr == dummy_buffer)
144        return;
145    if(!_zz_ready)
146        LOADSYM(free);
147    free_orig(ptr);
148}
149
150void *realloc(void *ptr, size_t size)
151{
152    void *ret;
153    if(ptr == dummy_buffer)
154        return ptr;
155    if(!_zz_ready)
156        LOADSYM(realloc);
157    ret = realloc_orig(ptr, size);
158    if(ret == NULL && _zz_memory && errno == ENOMEM)
159        raise(SIGKILL);
160    return ret;
161}
162
163void *valloc(size_t size)
164{
165    void *ret;
166    if(!_zz_ready)
167        LOADSYM(valloc);
168    ret = valloc_orig(size);
169    if(ret == NULL && _zz_memory && errno == ENOMEM)
170        raise(SIGKILL);
171    return ret;
172}
173
174#ifdef HAVE_MEMALIGN
175void *memalign(size_t boundary, size_t size)
176{
177    void *ret;
178    if(!_zz_ready)
179        LOADSYM(memalign);
180    ret = memalign_orig(boundary, size);
181    if(ret == NULL && _zz_memory && errno == ENOMEM)
182        raise(SIGKILL);
183    return ret;
184}
185#endif
186
187#ifdef HAVE_POSIX_MEMALIGN
188int posix_memalign(void **memptr, size_t alignment, size_t size)
189{
190    int ret;
191    if(!_zz_ready)
192        LOADSYM(posix_memalign);
193    ret = posix_memalign_orig(memptr, alignment, size);
194    if(ret == ENOMEM && _zz_memory)
195        raise(SIGKILL);
196    return ret;
197}
198#endif
199
200/* Table used for mmap() and munmap() */
201void **maps = NULL;
202int nbmaps = 0;
203
204#define MMAP(fn, off_t) \
205    do { \
206        if(!_zz_ready) \
207            LOADSYM(fn); \
208        ret = ORIG(fn)(start, length, prot, flags, fd, offset); \
209        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
210            return ret; \
211        if(ret && length) \
212        { \
213            char *b = malloc(length); \
214            int i, oldpos; \
215            for(i = 0; i < nbmaps; i += 2) \
216                if(maps[i] == NULL) \
217                    break; \
218            if(i == nbmaps) \
219            { \
220                nbmaps += 2; \
221                maps = realloc(maps, nbmaps * sizeof(void *)); \
222            } \
223            maps[i] = b; \
224            maps[i + 1] = ret; \
225            oldpos = _zz_getpos(fd); \
226            _zz_setpos(fd, offset); /* mmap() maps the fd at offset 0 */ \
227            memcpy(b, ret, length); /* FIXME: get rid of this */ \
228            _zz_fuzz(fd, (uint8_t *)b, length); \
229            _zz_setpos(fd, oldpos); \
230            ret = b; \
231            if(length >= 4) \
232                debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p \"%c%c%c%c...", \
233                      start, (long int)length, prot, flags, fd, \
234                      (long long int)offset, ret, b[0], b[1], b[2], b[3]); \
235            else \
236                debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p \"%c...", \
237                      start, (long int)length, prot, flags, fd, \
238                      (long long int)offset, ret, b[0]); \
239        } \
240        else \
241            debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p", \
242                  start, (long int)length, prot, flags, fd, \
243                  (long long int)offset, ret); \
244    } while(0)
245
246void *mmap(void *start, size_t length, int prot, int flags,
247           int fd, off_t offset)
248{
249    void *ret; MMAP(mmap, off_t); return ret;
250}
251
252#ifdef HAVE_MMAP64
253void *mmap64(void *start, size_t length, int prot, int flags,
254             int fd, off64_t offset)
255{
256    void *ret; MMAP(mmap64, off64_t); return ret;
257}
258#endif
259
260int munmap(void *start, size_t length)
261{
262    int ret, i;
263
264    if(!_zz_ready)
265        LOADSYM(munmap);
266    for(i = 0; i < nbmaps; i++)
267    {
268        if(maps[i] != start)
269            continue;
270
271        free(start);
272        ret = munmap_orig(maps[i + 1], length);
273        maps[i] = NULL;
274        maps[i + 1] = NULL;
275        debug("munmap(%p, %li) = %i", start, (long int)length, ret);
276        return ret;
277    }
278
279    return munmap_orig(start, length);
280}
281
282#ifdef HAVE_MAP_FD
283kern_return_t map_fd(int fd, vm_offset_t offset, vm_offset_t *addr,
284                     boolean_t find_space, vm_size_t numbytes)
285{
286    kern_return_t ret;
287
288    if(!_zz_ready)
289        LOADSYM(map_fd);
290    ret = map_fd_orig(fd, offset, addr, find_space, numbytes);
291    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
292        return ret;
293
294    if(ret == 0 && numbytes)
295    {
296        /* FIXME: do we also have to rewind the filedescriptor like in mmap? */
297        char *b = malloc(numbytes);
298        memcpy(b, (void *)*addr, numbytes);
299        _zz_fuzz(fd, (void *)b, numbytes);
300        *addr = (vm_offset_t)b;
301        /* FIXME: the map is never freed; there is no such thing as unmap_fd,
302         * but I suppose that kind of map should go when the filedescriptor is
303         * closed (unlike mmap, which returns a persistent buffer). */
304
305        if(numbytes >= 4)
306           debug("map_fd(%i, %lli, &%p, %i, %lli) = %i \"%c%c%c%c", fd,
307                 (long long int)offset, (void *)*addr, (int)find_space,
308                 (long long int)numbytes, ret, b[0], b[1], b[2], b[3]);
309        else
310           debug("map_fd(%i, %lli, &%p, %i, %lli) = %i \"%c", fd,
311                 (long long int)offset, (void *)*addr, (int)find_space,
312                 (long long int)numbytes, ret, b[0]);
313    }
314    else
315        debug("map_fd(%i, %lli, &%p, %i, %lli) = %i", fd, (long long int)offset,
316              (void *)*addr, (int)find_space, (long long int)numbytes, ret);
317
318    return ret;
319}
320#endif
321
Note: See TracBrowser for help on using the repository browser.