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

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