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

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