source: zzuf/trunk/src/load-fd.c @ 1621

Last change on this file since 1621 was 1621, checked in by Sam Hocevar, 14 years ago
  • Factor regex stuff into fd.c, so that <regex.h> isn’t needed otherwhere.
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: load-fd.c 1621 2007-01-07 21:14:26Z 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-fd.c: loaded file descriptor functions
17 */
18
19#include "config.h"
20
21/* Can't remember what that's for */
22#define _GNU_SOURCE
23/* Use this to get lseek64() on glibc systems */
24#define _LARGEFILE64_SOURCE
25
26#if defined HAVE_STDINT_H
27#   include <stdint.h>
28#elif defined HAVE_INTTYPES_H
29#   include <inttypes.h>
30#endif
31#include <stdlib.h>
32#include <string.h>
33#include <dlfcn.h>
34
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <sys/mman.h>
38#include <unistd.h>
39#include <fcntl.h>
40#include <stdarg.h>
41
42#include "libzzuf.h"
43#include "debug.h"
44#include "fuzz.h"
45#include "load.h"
46#include "fd.h"
47
48/* Library functions that we divert */
49static int     (*open_orig)    (const char *file, int oflag, ...);
50#ifdef HAVE_OPEN64
51static int     (*open64_orig)  (const char *file, int oflag, ...);
52#endif
53static int     (*accept_orig)  (int sockfd, struct sockaddr *addr,
54                                socklen_t *addrlen);
55static int     (*socket_orig)  (int domain, int type, int protocol);
56static ssize_t (*read_orig)    (int fd, void *buf, size_t count);
57static off_t   (*lseek_orig)   (int fd, off_t offset, int whence);
58#ifdef HAVE_LSEEK64
59static off64_t (*lseek64_orig) (int fd, off64_t offset, int whence);
60#endif
61static void *  (*mmap_orig)    (void *start, size_t length, int prot,
62                                int flags, int fd, off_t offset);
63#ifdef HAVE_LSEEK64
64static void *  (*mmap64_orig)  (void *start, size_t length, int prot,
65                                int flags, int fd, off64_t offset);
66#endif
67static int     (*munmap_orig)  (void *start, size_t length);
68static int     (*close_orig)   (int fd);
69
70
71void _zz_load_fd(void)
72{
73    LOADSYM(open);
74#ifdef HAVE_OPEN64
75    LOADSYM(open64);
76#endif
77    LOADSYM(accept);
78    LOADSYM(socket);
79    LOADSYM(read);
80    LOADSYM(lseek);
81#ifdef HAVE_LSEEK64
82    LOADSYM(lseek64);
83#endif
84    LOADSYM(mmap);
85#ifdef HAVE_MMAP64
86    LOADSYM(mmap64);
87#endif
88    LOADSYM(munmap);
89    LOADSYM(close);
90}
91
92#define OPEN(fn) \
93    do \
94    { \
95        int mode = 0; \
96        if(!_zz_ready) \
97            LOADSYM(fn); \
98        if(oflag & O_CREAT) \
99        { \
100            va_list va; \
101            va_start(va, oflag); \
102            mode = va_arg(va, int); \
103            va_end(va); \
104            ret = ORIG(fn)(file, oflag, mode); \
105        } \
106        else \
107        { \
108            ret = ORIG(fn)(file, oflag); \
109        } \
110        if(!_zz_ready || _zz_disabled) \
111            return ret; \
112        if(ret >= 0 \
113            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY) \
114            && _zz_mustwatch(file)) \
115        { \
116            if(oflag & O_CREAT) \
117                debug(STR(fn) "(\"%s\", %i, %i) = %i", \
118                      file, oflag, mode, ret); \
119            else \
120                debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
121            _zz_register(ret); \
122        } \
123    } while(0)
124
125int open(const char *file, int oflag, ...)
126{
127    int ret; OPEN(open); return ret;
128}
129
130#ifdef HAVE_OPEN64
131int open64(const char *file, int oflag, ...)
132{
133    int ret; OPEN(open64); return ret;
134}
135#endif
136
137int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
138{
139    int ret;
140
141    if(!_zz_ready)
142        LOADSYM(accept);
143    ret = accept_orig(sockfd, addr, addrlen);
144    if(!_zz_ready || _zz_disabled || !_zz_network)
145        return ret;
146
147    if(ret >= 0)
148    {
149        debug("accept(%i, %p, %p) = %i", sockfd, addr, addrlen, ret);
150        _zz_register(ret);
151    }
152
153    return ret;
154}
155
156int socket(int domain, int type, int protocol)
157{
158    int ret;
159
160    if(!_zz_ready)
161        LOADSYM(socket);
162    ret = socket_orig(domain, type, protocol);
163    if(!_zz_ready || _zz_disabled || !_zz_network)
164        return ret;
165
166    if(ret >= 0)
167    {
168        debug("socket(%i, %i, %i) = %i", domain, type, protocol, ret);
169        _zz_register(ret);
170    }
171
172    return ret;
173}
174
175ssize_t read(int fd, void *buf, size_t count)
176{
177    int ret;
178
179    if(!_zz_ready)
180        LOADSYM(read);
181    ret = read_orig(fd, buf, count);
182    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
183        return ret;
184
185    debug("read(%i, %p, %li) = %i", fd, buf, (long int)count, ret);
186    if(ret > 0)
187    {
188        _zz_fuzz(fd, buf, ret);
189        _zz_addpos(fd, ret);
190    }
191
192    /* Sanity check, can be OK though (for instance with a character device) */
193#ifdef HAVE_LSEEK64
194    if(lseek64_orig(fd, 0, SEEK_CUR) != _zz_getpos(fd))
195#else
196    if(lseek_orig(fd, 0, SEEK_CUR) != _zz_getpos(fd))
197#endif
198        debug("warning: offset inconsistency");
199
200    return ret;
201}
202
203#define LSEEK(fn, off_t) \
204    do \
205    { \
206        if(!_zz_ready) \
207            LOADSYM(fn); \
208        ret = ORIG(fn)(fd, offset, whence); \
209        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
210            return ret; \
211        debug(STR(fn)"(%i, %lli, %i) = %lli", \
212              fd, (long long int)offset, whence, (long long int)ret); \
213        if(ret != (off_t)-1) \
214            _zz_setpos(fd, ret); \
215    } while(0)
216
217off_t lseek(int fd, off_t offset, int whence)
218{
219    off_t ret;
220    LSEEK(lseek, off_t);
221    return ret;
222}
223
224#ifdef HAVE_LSEEK64
225off64_t lseek64(int fd, off64_t offset, int whence)
226{
227    off64_t ret;
228    LSEEK(lseek64, off64_t);
229    return ret;
230}
231#endif
232
233/* Used for mmap() and munmap() */
234void **maps = NULL;
235int nbmaps = 0;
236
237#define MMAP(fn, off_t) \
238    do { \
239        if(!_zz_ready) \
240            LOADSYM(fn); \
241        ret = ORIG(fn)(start, length, prot, flags, fd, offset); \
242        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
243            return ret; \
244        if(ret) \
245        { \
246            void *tmp = malloc(length); \
247            int i; \
248            for(i = 0; i < nbmaps; i += 2) \
249                if(maps[i] == NULL) \
250                    break; \
251            if(i == nbmaps) \
252            { \
253                nbmaps += 2; \
254                maps = realloc(maps, nbmaps * sizeof(void *)); \
255            } \
256            maps[i] = tmp; \
257            maps[i + 1] = ret; \
258            memcpy(tmp, ret, length); /* FIXME: get rid of this */ \
259            _zz_fuzz(fd, tmp, length); \
260            ret = tmp; \
261        } \
262        debug(STR(fn)"(%p, %li, %i, %i, %i, %lli) = %p", start, \
263              (long int)length, prot, flags, fd, (long long int)offset, ret); \
264    } while(0)
265
266void *mmap(void *start, size_t length, int prot, int flags,
267           int fd, off_t offset)
268{
269    void *ret; MMAP(mmap, off_t); return ret;
270}
271
272#ifdef HAVE_MMAP64
273void *mmap64(void *start, size_t length, int prot, int flags,
274             int fd, off64_t offset)
275{
276    void *ret; MMAP(mmap64, off64_t); return ret;
277}
278#endif
279
280int munmap(void *start, size_t length)
281{
282    int ret, i;
283
284    if(!_zz_ready)
285        LOADSYM(munmap);
286    for(i = 0; i < nbmaps; i++)
287    {
288        if(maps[i] != start)
289            continue;
290
291        free(start);
292        ret = munmap_orig(maps[i + 1], length);
293        maps[i] = NULL;
294        maps[i + 1] = NULL;
295        debug("munmap(%p, %li) = %i", start, (long int)length, ret);
296        return ret;
297    }
298
299    return munmap_orig(start, length);
300}
301
302int close(int fd)
303{
304    int ret;
305
306    if(!_zz_ready)
307        LOADSYM(close);
308
309    /* Hey, it’s our debug channel! Silently pretend we closed it. */
310    if(fd == DEBUG_FILENO)
311        return 0;
312
313    ret = close_orig(fd);
314    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
315        return ret;
316
317    debug("close(%i) = %i", fd, ret);
318    _zz_unregister(fd);
319
320    return ret;
321}
322
Note: See TracBrowser for help on using the repository browser.