source: zzuf/trunk/src/lib-fd.c @ 1683

Last change on this file since 1683 was 1683, checked in by Sam Hocevar, 15 years ago
  • Moved files around.
  • Property svn:keywords set to Id
File size: 7.3 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006, 2007 Sam Hocevar <sam@zoy.org>
4 *                2007 Rémi Denis-Courmont <rdenis#simphalempin:com>
5 *                2007 Clément Stenac <zorglub#diwi:org>
6 *                All Rights Reserved
7 *
8 *  $Id: lib-fd.c 1683 2007-01-17 13:46:38Z sam $
9 *
10 *  This program is free software. It comes without any warranty, to
11 *  the extent permitted by applicable law. You can redistribute it
12 *  and/or modify it under the terms of the Do What The Fuck You Want
13 *  To Public License, Version 2, as published by Sam Hocevar. See
14 *  http://sam.zoy.org/wtfpl/COPYING for more details.
15 */
16
17/*
18 *  load-fd.c: loaded file descriptor functions
19 */
20
21#include "config.h"
22
23/* Need this for RTLD_NEXT */
24#define _GNU_SOURCE
25/* Use this to get lseek64() on glibc systems */
26#define _LARGEFILE64_SOURCE
27
28#if defined HAVE_STDINT_H
29#   include <stdint.h>
30#elif defined HAVE_INTTYPES_H
31#   include <inttypes.h>
32#endif
33#include <stdlib.h>
34#include <string.h>
35#include <dlfcn.h>
36
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <sys/uio.h>
40#include <unistd.h>
41#include <fcntl.h>
42#include <stdarg.h>
43
44#include "libzzuf.h"
45#include "lib-load.h"
46#include "debug.h"
47#include "fuzz.h"
48#include "fd.h"
49
50#ifdef HAVE_SOCKLEN_T
51#   define SOCKLEN_T socklen_t
52#else
53#   define SOCKLEN_T int
54#endif
55
56/* Library functions that we divert */
57static int     (*open_orig)    (const char *file, int oflag, ...);
58#ifdef HAVE_OPEN64
59static int     (*open64_orig)  (const char *file, int oflag, ...);
60#endif
61static int     (*accept_orig)  (int sockfd, struct sockaddr *addr,
62                                SOCKLEN_T *addrlen);
63static int     (*socket_orig)  (int domain, int type, int protocol);
64static ssize_t (*read_orig)    (int fd, void *buf, size_t count);
65static ssize_t (*readv_orig)   (int fd, const struct iovec *iov, int count);
66static ssize_t (*pread_orig)   (int fd, void *buf, size_t count, off_t offset);
67static off_t   (*lseek_orig)   (int fd, off_t offset, int whence);
68#ifdef HAVE_LSEEK64
69static off64_t (*lseek64_orig) (int fd, off64_t offset, int whence);
70#endif
71static int     (*close_orig)   (int fd);
72
73#define OPEN(fn) \
74    do \
75    { \
76        int mode = 0; \
77        LOADSYM(fn); \
78        if(oflag & O_CREAT) \
79        { \
80            va_list va; \
81            va_start(va, oflag); \
82            mode = va_arg(va, int); \
83            va_end(va); \
84            ret = ORIG(fn)(file, oflag, mode); \
85        } \
86        else \
87        { \
88            ret = ORIG(fn)(file, oflag); \
89        } \
90        if(!_zz_ready || _zz_disabled) \
91            return ret; \
92        if(ret >= 0 \
93            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY) \
94            && _zz_mustwatch(file)) \
95        { \
96            if(oflag & O_CREAT) \
97                debug(STR(fn) "(\"%s\", %i, %i) = %i", \
98                      file, oflag, mode, ret); \
99            else \
100                debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
101            _zz_register(ret); \
102        } \
103    } while(0)
104
105int open(const char *file, int oflag, ...)
106{
107    int ret; OPEN(open); return ret;
108}
109
110#ifdef HAVE_OPEN64
111int open64(const char *file, int oflag, ...)
112{
113    int ret; OPEN(open64); return ret;
114}
115#endif
116
117int accept(int sockfd, struct sockaddr *addr, SOCKLEN_T *addrlen)
118{
119    int ret;
120
121    LOADSYM(accept);
122    ret = accept_orig(sockfd, addr, addrlen);
123    if(!_zz_ready || _zz_disabled || !_zz_network)
124        return ret;
125
126    if(ret >= 0)
127    {
128        debug("accept(%i, %p, %p) = %i", sockfd, addr, addrlen, ret);
129        _zz_register(ret);
130    }
131
132    return ret;
133}
134
135int socket(int domain, int type, int protocol)
136{
137    int ret;
138
139    LOADSYM(socket);
140    ret = socket_orig(domain, type, protocol);
141    if(!_zz_ready || _zz_disabled || !_zz_network)
142        return ret;
143
144    if(ret >= 0)
145    {
146        debug("socket(%i, %i, %i) = %i", domain, type, protocol, ret);
147        _zz_register(ret);
148    }
149
150    return ret;
151}
152
153static void offset_check(int fd)
154{
155    /* Sanity check, can be OK though (for instance with a character device) */
156#ifdef HAVE_LSEEK64
157    off64_t ret;
158    LOADSYM(lseek64);
159    ret = lseek64_orig(fd, 0, SEEK_CUR);
160#else
161    off_t ret;
162    LOADSYM(lseek);
163    ret = lseek_orig(fd, 0, SEEK_CUR);
164#endif
165    if(ret != -1 && ret != _zz_getpos(fd))
166        debug("warning: offset inconsistency");
167}
168
169ssize_t read(int fd, void *buf, size_t count)
170{
171    int ret;
172
173    LOADSYM(read);
174    ret = read_orig(fd, buf, count);
175    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
176        return ret;
177
178    if(ret > 0)
179    {
180        char *b = buf;
181
182        _zz_fuzz(fd, buf, ret);
183        _zz_addpos(fd, ret);
184
185        if(ret >= 4)
186            debug("read(%i, %p, %li) = %i \"%c%c%c%c...", fd, buf,
187                  (long int)count, ret, b[0], b[1], b[2], b[3]);
188        else
189            debug("read(%i, %p, %li) = %i \"%c...", fd, buf,
190                  (long int)count, ret, b[0]);
191    }
192    else
193        debug("read(%i, %p, %li) = %i", fd, buf, (long int)count, ret);
194
195    offset_check(fd);
196    return ret;
197}
198
199ssize_t readv(int fd, const struct iovec *iov, int count)
200{
201    ssize_t ret;
202
203    LOADSYM(readv);
204    ret = readv_orig(fd, iov, count);
205    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
206        return ret;
207
208    debug("readv(%i, %p, %i) = %li", fd, iov, count, (long int)ret);
209
210    while(ret > 0)
211    {
212        void *b = iov->iov_base;
213        size_t len = iov->iov_len;
214
215        if(len > (size_t)ret)
216            len = ret;
217
218        _zz_fuzz(fd, b, len);
219        _zz_addpos(fd, len);
220
221        iov++;
222        ret -= len;
223    }
224
225    offset_check(fd);
226    return ret;
227}
228
229ssize_t pread(int fd, void *buf, size_t count, off_t offset)
230{
231    int ret;
232
233    LOADSYM(pread);
234    ret = pread_orig(fd, buf, count, offset);
235    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
236        return ret;
237
238    if(ret > 0)
239    {
240        long int curoff = _zz_getpos(fd);
241        char *b = buf;
242
243        _zz_setpos(fd, offset);
244        _zz_fuzz(fd, buf, ret);
245        _zz_setpos(fd, curoff);
246
247        if(ret >= 4)
248            debug("pread(%i, %p, %li, %li) = %i \"%c%c%c%c...", fd, buf,
249                  (long int)count, (long int)offset, ret,
250                  b[0], b[1], b[2], b[3]);
251        else
252            debug("pread(%i, %p, %li, %li) = %i \"%c...", fd, buf,
253                  (long int)count, (long int)offset, ret, b[0]);
254    }
255    else
256        debug("pread(%i, %p, %li, %li) = %i", fd, buf,
257              (long int)count, (long int)offset, ret);
258
259    return ret;
260}
261
262#define LSEEK(fn, off_t) \
263    do \
264    { \
265        LOADSYM(fn); \
266        ret = ORIG(fn)(fd, offset, whence); \
267        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
268            return ret; \
269        debug(STR(fn)"(%i, %lli, %i) = %lli", \
270              fd, (long long int)offset, whence, (long long int)ret); \
271        if(ret != (off_t)-1) \
272            _zz_setpos(fd, ret); \
273    } while(0)
274
275off_t lseek(int fd, off_t offset, int whence)
276{
277    off_t ret;
278    LSEEK(lseek, off_t);
279    return ret;
280}
281
282#ifdef HAVE_LSEEK64
283off64_t lseek64(int fd, off64_t offset, int whence)
284{
285    off64_t ret;
286    LSEEK(lseek64, off64_t);
287    return ret;
288}
289#endif
290
291int close(int fd)
292{
293    int ret;
294
295    /* Hey, it’s our debug channel! Silently pretend we closed it. */
296    if(fd == DEBUG_FILENO)
297        return 0;
298
299    LOADSYM(close);
300    ret = close_orig(fd);
301    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
302        return ret;
303
304    debug("close(%i) = %i", fd, ret);
305    _zz_unregister(fd);
306
307    return ret;
308}
309
Note: See TracBrowser for help on using the repository browser.