source: zzuf/trunk/src/preload.c @ 1490

Last change on this file since 1490 was 1490, checked in by Sam Hocevar, 16 years ago
  • Rename zzuf_preload to zzuf_preload_libc. You never know.
  • Property svn:keywords set to Id
File size: 7.6 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: preload.c 1490 2006-12-15 18:48:24Z 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 *  preload.c: preloaded library 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() */
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 <stdio.h>
32#include <sys/types.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <fcntl.h>
36#include <regex.h>
37
38#include <stdarg.h>
39#include <dlfcn.h>
40
41#include "libzzuf.h"
42#include "debug.h"
43#include "fuzz.h"
44#include "preload.h"
45
46/* Library functions that we divert */
47static FILE *  (*fopen_orig)   (const char *path, const char *mode);
48static FILE *  (*fopen64_orig) (const char *path, const char *mode);
49static int     (*fseek_orig)   (FILE *stream, long offset, int whence);
50static size_t  (*fread_orig)   (void *ptr, size_t size, size_t nmemb,
51                                FILE *stream);
52static int     (*fclose_orig)  (FILE *fp);
53
54static int     (*open_orig)    (const char *file, int oflag, ...);
55static int     (*open64_orig)  (const char *file, int oflag, ...);
56static ssize_t (*read_orig)    (int fd, void *buf, size_t count);
57static off_t   (*lseek_orig)   (int fd, off_t offset, int whence);
58static off64_t (*lseek64_orig) (int fd, off64_t offset, int whence);
59static int     (*close_orig)   (int fd);
60
61#define STR(x) #x
62#define ORIG(x) x##_orig
63
64#define LOADSYM(x) \
65    do { \
66        ORIG(x) = dlsym(RTLD_NEXT, STR(x)); \
67        if(!ORIG(x)) \
68            abort(); \
69    } while(0)
70
71void zzuf_preload_libc(void)
72{
73    LOADSYM(fopen);
74    LOADSYM(fopen64);
75    LOADSYM(fseek);
76    LOADSYM(fread);
77    LOADSYM(fclose);
78
79    LOADSYM(open);
80    LOADSYM(open64);
81    LOADSYM(read);
82    LOADSYM(lseek);
83    LOADSYM(lseek64);
84    LOADSYM(close);
85}
86
87/* Our function wrappers */
88#define FOPEN(fn) \
89    do \
90    { \
91        if(!_zzuf_ready) \
92            LOADSYM(fn); \
93        ret = ORIG(fn)(path, mode); \
94        if(!_zzuf_ready) \
95            return ret; \
96        if(ret) \
97        { \
98            if(_zzuf_include && \
99                regexec(_zzuf_include, path, 0, NULL, 0) == REG_NOMATCH) \
100                /* not included: ignore */ ; \
101            else if(_zzuf_exclude && \
102                    regexec(_zzuf_exclude, path, 0, NULL, 0) != REG_NOMATCH) \
103                /* excluded: ignore */ ; \
104            else \
105            { \
106                int fd = fileno(ret); \
107                files[fd].managed = 1; \
108                files[fd].pos = 0; \
109                debug(STR(fn) "(\"%s\", \"%s\") = %p", path, mode, ret); \
110            } \
111        } \
112    } while(0)
113
114FILE *fopen(const char *path, const char *mode)
115{
116    FILE *ret; FOPEN(fopen); return ret;
117}
118
119FILE *fopen64(const char *path, const char *mode)
120{
121    FILE *ret; FOPEN(fopen64); return ret;
122}
123
124int fseek(FILE *stream, long offset, int whence)
125{
126    int ret, fd;
127
128    if(!_zzuf_ready)
129        LOADSYM(fseek);
130    ret = fseek_orig(stream, offset, whence);
131    if(!_zzuf_ready)
132        return ret;
133
134    fd = fileno(stream);
135    if(!files[fd].managed)
136        return ret;
137
138    debug("fseek(%p, %li, %i) = %i", stream, offset, whence, ret);
139    if(ret == 0)
140    {
141        switch(whence)
142        {
143            case SEEK_SET: files[fd].pos = offset; break;
144            case SEEK_CUR: files[fd].pos += offset; break;
145            case SEEK_END: files[fd].pos = ftell(stream); break;
146        }
147    }
148    return ret;
149}
150
151size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
152{
153    size_t ret;
154    int fd;
155
156    if(!_zzuf_ready)
157        LOADSYM(fread);
158    ret = fread_orig(ptr, size, nmemb, stream);
159    if(!_zzuf_ready)
160        return ret;
161
162    fd = fileno(stream);
163    if(!files[fd].managed)
164        return ret;
165
166    debug("fread(%p, %li, %li, %p) = %li",
167          ptr, (long int)size, (long int)nmemb, stream, (long int)ret);
168    if(ret > 0)
169    {
170        zzuf_fuzz(fd, ptr, ret * size);
171        files[fd].pos += ret * size;
172    }
173    return ret;
174}
175
176int fclose(FILE *fp)
177{
178    int ret, fd;
179
180    if(!_zzuf_ready)
181        LOADSYM(fclose);
182    fd = fileno(fp);
183    ret = fclose_orig(fp);
184    if(!_zzuf_ready)
185        return ret;
186
187    if(!files[fd].managed)
188        return ret;
189
190    debug("fclose(%p) = %i", fp, ret);
191    files[fd].managed = 0;
192
193    return ret;
194}
195
196#define OPEN(fn) \
197    do \
198    { \
199        int mode = 0; \
200        if(!_zzuf_ready) \
201            LOADSYM(fn); \
202        if(oflag & O_CREAT) \
203        { \
204            va_list va; \
205            va_start(va, oflag); \
206            mode = va_arg(va, int); \
207            va_end(va); \
208            ret = ORIG(fn)(file, oflag, mode); \
209        } \
210        else \
211        { \
212            ret = ORIG(fn)(file, oflag); \
213        } \
214        if(!_zzuf_ready) \
215            return ret; \
216        if(ret >= 0 \
217            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY)) \
218        { \
219            if(_zzuf_include && \
220                regexec(_zzuf_include, file, 0, NULL, 0) == REG_NOMATCH) \
221                /* not included: ignore */ ; \
222            else if(_zzuf_exclude && \
223                    regexec(_zzuf_exclude, file, 0, NULL, 0) != REG_NOMATCH) \
224                /* excluded: ignore */ ; \
225            else \
226            { \
227                if(oflag & O_CREAT) \
228                    debug(STR(fn) "(\"%s\", %i, %i) = %i", \
229                          file, oflag, mode, ret); \
230                else \
231                    debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
232                files[ret].managed = 1; \
233                files[ret].pos = 0; \
234            } \
235        } \
236    } while(0)
237
238int open(const char *file, int oflag, ...)
239{
240    int ret; OPEN(open); return ret;
241}
242
243int open64(const char *file, int oflag, ...)
244{
245    int ret; OPEN(open64); return ret;
246}
247
248ssize_t read(int fd, void *buf, size_t count)
249{
250    int ret;
251
252    if(!_zzuf_ready)
253        LOADSYM(read);
254    ret = read_orig(fd, buf, count);
255    if(!_zzuf_ready)
256        return ret;
257
258    if(!files[fd].managed)
259        return ret;
260
261    debug("read(%i, %p, %li) = %i", fd, buf, (long int)count, ret);
262    if(ret > 0)
263    {
264        zzuf_fuzz(fd, buf, ret);
265        files[fd].pos += ret;
266    }
267
268    /* Sanity check, can be OK though (for instance with a character device) */
269    if((uint64_t)lseek64_orig(fd, 0, SEEK_CUR) != files[fd].pos)
270        debug("warning: offset inconsistency");
271
272    return ret;
273}
274
275#define LSEEK(fn, off_t) \
276    do { \
277        if(!_zzuf_ready) \
278            LOADSYM(fn); \
279        ret = ORIG(fn)(fd, offset, whence); \
280        if(!_zzuf_ready) \
281            return ret; \
282        if(!files[fd].managed) \
283            return ret; \
284        debug(STR(fn)"(%i, %lli, %i) = %lli", \
285              fd, (long long int)offset, whence, (long long int)ret); \
286        if(ret != (off_t)-1) \
287            files[fd].pos = (int64_t)ret; \
288    } while(0)
289
290off_t lseek(int fd, off_t offset, int whence)
291{
292    off_t ret;
293    LSEEK(lseek, off_t);
294    return ret;
295}
296
297off64_t lseek64(int fd, off64_t offset, int whence)
298{
299    off64_t ret;
300    LSEEK(lseek64, off64_t);
301    return ret;
302}
303
304int close(int fd)
305{
306    int ret;
307
308    if(!_zzuf_ready)
309        LOADSYM(close);
310    ret = close_orig(fd);
311    if(!_zzuf_ready)
312        return ret;
313
314    if(!files[fd].managed)
315        return ret;
316
317    debug("close(%i) = %i", fd, ret);
318    files[fd].managed = 0;
319
320    return ret;
321}
322
Note: See TracBrowser for help on using the repository browser.