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

Last change on this file since 1639 was 1639, checked in by Sam Hocevar, 14 years ago
  • Split load-fd.c into load-fd.c and load-mem.c (mmap, etc.).
  • Property svn:keywords set to Id
File size: 5.8 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: load-fd.c 1639 2007-01-10 14:57:22Z 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 *  load-fd.c: loaded file descriptor functions
17 */
18
19#include "config.h"
20
21/* Need this for RTLD_NEXT */
22#define _GNU_SOURCE
23/* Use this to get lseek64() on glibc systems */
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 <stdlib.h>
32#include <string.h>
33#include <dlfcn.h>
34
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <unistd.h>
38#include <fcntl.h>
39#include <stdarg.h>
40
41#include "libzzuf.h"
42#include "debug.h"
43#include "fuzz.h"
44#include "load.h"
45#include "fd.h"
46
47#ifdef HAVE_SOCKLEN_T
48#   define SOCKLEN_T socklen_t
49#else
50#   define SOCKLEN_T int
51#endif
52
53/* Library functions that we divert */
54static int     (*open_orig)    (const char *file, int oflag, ...);
55#ifdef HAVE_OPEN64
56static int     (*open64_orig)  (const char *file, int oflag, ...);
57#endif
58static int     (*accept_orig)  (int sockfd, struct sockaddr *addr,
59                                SOCKLEN_T *addrlen);
60static int     (*socket_orig)  (int domain, int type, int protocol);
61static ssize_t (*read_orig)    (int fd, void *buf, size_t count);
62static off_t   (*lseek_orig)   (int fd, off_t offset, int whence);
63#ifdef HAVE_LSEEK64
64static off64_t (*lseek64_orig) (int fd, off64_t offset, int whence);
65#endif
66static int     (*close_orig)   (int fd);
67
68
69void _zz_load_fd(void)
70{
71    LOADSYM(open);
72#ifdef HAVE_OPEN64
73    LOADSYM(open64);
74#endif
75    LOADSYM(accept);
76    LOADSYM(socket);
77    LOADSYM(read);
78    LOADSYM(lseek);
79#ifdef HAVE_LSEEK64
80    LOADSYM(lseek64);
81#endif
82    LOADSYM(close);
83}
84
85#define OPEN(fn) \
86    do \
87    { \
88        int mode = 0; \
89        if(!_zz_ready) \
90            LOADSYM(fn); \
91        if(oflag & O_CREAT) \
92        { \
93            va_list va; \
94            va_start(va, oflag); \
95            mode = va_arg(va, int); \
96            va_end(va); \
97            ret = ORIG(fn)(file, oflag, mode); \
98        } \
99        else \
100        { \
101            ret = ORIG(fn)(file, oflag); \
102        } \
103        if(!_zz_ready || _zz_disabled) \
104            return ret; \
105        if(ret >= 0 \
106            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY) \
107            && _zz_mustwatch(file)) \
108        { \
109            if(oflag & O_CREAT) \
110                debug(STR(fn) "(\"%s\", %i, %i) = %i", \
111                      file, oflag, mode, ret); \
112            else \
113                debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
114            _zz_register(ret); \
115        } \
116    } while(0)
117
118int open(const char *file, int oflag, ...)
119{
120    int ret; OPEN(open); return ret;
121}
122
123#ifdef HAVE_OPEN64
124int open64(const char *file, int oflag, ...)
125{
126    int ret; OPEN(open64); return ret;
127}
128#endif
129
130int accept(int sockfd, struct sockaddr *addr, SOCKLEN_T *addrlen)
131{
132    int ret;
133
134    if(!_zz_ready)
135        LOADSYM(accept);
136    ret = accept_orig(sockfd, addr, addrlen);
137    if(!_zz_ready || _zz_disabled || !_zz_network)
138        return ret;
139
140    if(ret >= 0)
141    {
142        debug("accept(%i, %p, %p) = %i", sockfd, addr, addrlen, ret);
143        _zz_register(ret);
144    }
145
146    return ret;
147}
148
149int socket(int domain, int type, int protocol)
150{
151    int ret;
152
153    if(!_zz_ready)
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
168ssize_t read(int fd, void *buf, size_t count)
169{
170    int ret;
171
172    if(!_zz_ready)
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    /* Sanity check, can be OK though (for instance with a character device) */
196#ifdef HAVE_LSEEK64
197    if(lseek64_orig(fd, 0, SEEK_CUR) != _zz_getpos(fd))
198#else
199    if(lseek_orig(fd, 0, SEEK_CUR) != _zz_getpos(fd))
200#endif
201        debug("warning: offset inconsistency");
202
203    return ret;
204}
205
206#define LSEEK(fn, off_t) \
207    do \
208    { \
209        if(!_zz_ready) \
210            LOADSYM(fn); \
211        ret = ORIG(fn)(fd, offset, whence); \
212        if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled) \
213            return ret; \
214        debug(STR(fn)"(%i, %lli, %i) = %lli", \
215              fd, (long long int)offset, whence, (long long int)ret); \
216        if(ret != (off_t)-1) \
217            _zz_setpos(fd, ret); \
218    } while(0)
219
220off_t lseek(int fd, off_t offset, int whence)
221{
222    off_t ret;
223    LSEEK(lseek, off_t);
224    return ret;
225}
226
227#ifdef HAVE_LSEEK64
228off64_t lseek64(int fd, off64_t offset, int whence)
229{
230    off64_t ret;
231    LSEEK(lseek64, off64_t);
232    return ret;
233}
234#endif
235
236int close(int fd)
237{
238    int ret;
239
240    if(!_zz_ready)
241        LOADSYM(close);
242
243    /* Hey, it’s our debug channel! Silently pretend we closed it. */
244    if(fd == DEBUG_FILENO)
245        return 0;
246
247    ret = close_orig(fd);
248    if(!_zz_ready || !_zz_iswatched(fd) || _zz_disabled)
249        return ret;
250
251    debug("close(%i) = %i", fd, ret);
252    _zz_unregister(fd);
253
254    return ret;
255}
256
Note: See TracBrowser for help on using the repository browser.