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

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