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

Last change on this file since 1678 was 1678, checked in by Sam Hocevar, 16 years ago
  • pread() implementation, thanks to Clément Stenac.
  • Property svn:keywords set to Id
File size: 7.6 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: load-fd.c 1678 2007-01-16 14:21:28Z 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 "debug.h"
46#include "fuzz.h"
47#include "load.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
74void _zz_load_fd(void)
75{
76    LOADSYM(open);
77#ifdef HAVE_OPEN64
78    LOADSYM(open64);
79#endif
80    LOADSYM(accept);
81    LOADSYM(socket);
82    LOADSYM(read);
83    LOADSYM(readv);
84    LOADSYM(pread);
85    LOADSYM(lseek);
86#ifdef HAVE_LSEEK64
87    LOADSYM(lseek64);
88#endif
89    LOADSYM(close);
90}
91
92#define OPEN(fn) \
93    do \
94    { \
95        int mode = 0; \
96        LOADSYM(fn); \
97        if(oflag & O_CREAT) \
98        { \
99            va_list va; \
100            va_start(va, oflag); \
101            mode = va_arg(va, int); \
102            va_end(va); \
103            ret = ORIG(fn)(file, oflag, mode); \
104        } \
105        else \
106        { \
107            ret = ORIG(fn)(file, oflag); \
108        } \
109        if(!_zz_ready || _zz_disabled) \
110            return ret; \
111        if(ret >= 0 \
112            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY) \
113            && _zz_mustwatch(file)) \
114        { \
115            if(oflag & O_CREAT) \
116                debug(STR(fn) "(\"%s\", %i, %i) = %i", \
117                      file, oflag, mode, ret); \
118            else \
119                debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
120            _zz_register(ret); \
121        } \
122    } while(0)
123
124int open(const char *file, int oflag, ...)
125{
126    int ret; OPEN(open); return ret;
127}
128
129#ifdef HAVE_OPEN64
130int open64(const char *file, int oflag, ...)
131{
132    int ret; OPEN(open64); return ret;
133}
134#endif
135
136int accept(int sockfd, struct sockaddr *addr, SOCKLEN_T *addrlen)
137{
138    int ret;
139
140    LOADSYM(accept);
141    ret = accept_orig(sockfd, addr, addrlen);
142    if(!_zz_ready || _zz_disabled || !_zz_network)
143        return ret;
144
145    if(ret >= 0)
146    {
147        debug("accept(%i, %p, %p) = %i", sockfd, addr, addrlen, ret);
148        _zz_register(ret);
149    }
150
151    return ret;
152}
153
154int socket(int domain, int type, int protocol)
155{
156    int ret;
157
158    LOADSYM(socket);
159    ret = socket_orig(domain, type, protocol);
160    if(!_zz_ready || _zz_disabled || !_zz_network)
161        return ret;
162
163    if(ret >= 0)
164    {
165        debug("socket(%i, %i, %i) = %i", domain, type, protocol, ret);
166        _zz_register(ret);
167    }
168
169    return ret;
170}
171
172static void offset_check(int fd)
173{
174    /* Sanity check, can be OK though (for instance with a character device) */
175#ifdef HAVE_LSEEK64
176    off64_t ret = lseek64_orig(fd, 0, SEEK_CUR);
177#else
178    off_t ret = lseek_orig(fd, 0, SEEK_CUR);
179#endif
180    if(ret != -1 && ret != _zz_getpos(fd))
181        debug("warning: offset inconsistency");
182}
183
184ssize_t read(int fd, void *buf, size_t count)
185{
186    int ret;
187
188    LOADSYM(read);
189    ret = read_orig(fd, buf, count);
190    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
191        return ret;
192
193    if(ret > 0)
194    {
195        char *b = buf;
196
197        _zz_fuzz(fd, buf, ret);
198        _zz_addpos(fd, ret);
199
200        if(ret >= 4)
201            debug("read(%i, %p, %li) = %i \"%c%c%c%c...", fd, buf,
202                  (long int)count, ret, b[0], b[1], b[2], b[3]);
203        else
204            debug("read(%i, %p, %li) = %i \"%c...", fd, buf,
205                  (long int)count, ret, b[0]);
206    }
207    else
208        debug("read(%i, %p, %li) = %i", fd, buf, (long int)count, ret);
209
210    offset_check(fd);
211    return ret;
212}
213
214ssize_t readv(int fd, const struct iovec *iov, int count)
215{
216    ssize_t ret;
217
218    LOADSYM(readv);
219    ret = readv_orig(fd, iov, count);
220    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
221        return ret;
222
223    debug("readv(%i, %p, %i) = %li", fd, iov, count, (long int)ret);
224
225    while(ret > 0)
226    {
227        void *b = iov->iov_base;
228        size_t len = iov->iov_len;
229
230        if(len > (size_t)ret)
231            len = ret;
232
233        _zz_fuzz(fd, b, len);
234        _zz_addpos(fd, len);
235
236        iov++;
237        ret -= len;
238    }
239
240    offset_check(fd);
241    return ret;
242}
243
244ssize_t pread(int fd, void *buf, size_t count, off_t offset)
245{
246    int ret;
247
248    LOADSYM(pread);
249    ret = pread_orig(fd, buf, count, offset);
250    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
251        return ret;
252
253    if(ret > 0)
254    {
255        long int curoff = _zz_getpos(fd);
256        char *b = buf;
257
258        _zz_setpos(fd, offset);
259        _zz_fuzz(fd, buf, ret);
260        _zz_setpos(fd, curoff);
261
262        if(ret >= 4)
263            debug("pread(%i, %p, %li, %li) = %i \"%c%c%c%c...", fd, buf,
264                  (long int)count, (long int)offset, ret,
265                  b[0], b[1], b[2], b[3]);
266        else
267            debug("pread(%i, %p, %li, %li) = %i \"%c...", fd, buf,
268                  (long int)count, (long int)offset, ret, b[0]);
269    }
270    else
271        debug("pread(%i, %p, %li, %li) = %i", fd, buf,
272              (long int)count, (long int)offset, ret);
273
274    return ret;
275}
276
277#define LSEEK(fn, off_t) \
278    do \
279    { \
280        LOADSYM(fn); \
281        ret = ORIG(fn)(fd, offset, whence); \
282        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
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            _zz_setpos(fd, 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
297#ifdef HAVE_LSEEK64
298off64_t lseek64(int fd, off64_t offset, int whence)
299{
300    off64_t ret;
301    LSEEK(lseek64, off64_t);
302    return ret;
303}
304#endif
305
306int close(int fd)
307{
308    int ret;
309
310    LOADSYM(close);
311
312    /* Hey, it’s our debug channel! Silently pretend we closed it. */
313    if(fd == DEBUG_FILENO)
314        return 0;
315
316    ret = close_orig(fd);
317    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
318        return ret;
319
320    debug("close(%i) = %i", fd, ret);
321    _zz_unregister(fd);
322
323    return ret;
324}
325
Note: See TracBrowser for help on using the repository browser.