* Added -p flag to cherry pick file descriptors that get fuzzed.
This commit is contained in:
parent
71c077ae58
commit
7693a37ae1
71
src/fd.c
71
src/fd.c
@ -34,6 +34,7 @@
|
||||
#include "debug.h"
|
||||
#include "libzzuf.h"
|
||||
#include "fd.h"
|
||||
#include "fuzz.h"
|
||||
|
||||
/* Regex stuff */
|
||||
#if defined HAVE_REGEX_H
|
||||
@ -41,6 +42,10 @@ static regex_t re_include, re_exclude;
|
||||
static int has_include = 0, has_exclude = 0;
|
||||
#endif
|
||||
|
||||
/* File descriptor cherry picking */
|
||||
static int *ranges = NULL;
|
||||
static int ranges_static[512];
|
||||
|
||||
/* File descriptor stuff. When program is launched, we use the static array of
|
||||
* 32 structures, which ought to be enough for most programs. If it happens
|
||||
* not to be the case, ie. if the process opens more than 32 file descriptors
|
||||
@ -49,7 +54,7 @@ static int has_include = 0, has_exclude = 0;
|
||||
#define STATIC_FILES 32
|
||||
static struct files
|
||||
{
|
||||
int managed, locked;
|
||||
int managed, locked, active;
|
||||
int64_t pos;
|
||||
/* Public stuff */
|
||||
struct fuzz fuzz;
|
||||
@ -89,6 +94,42 @@ void _zz_exclude(char const *regex)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function is the same as _zz_bytes() */
|
||||
void _zz_pick(char const *list)
|
||||
{
|
||||
char const *parser;
|
||||
unsigned int i, chunks;
|
||||
|
||||
/* Count commas */
|
||||
for(parser = list, chunks = 1; *parser; parser++)
|
||||
if(*parser == ',')
|
||||
chunks++;
|
||||
|
||||
/* TODO: free(ranges) if ranges != ranges_static */
|
||||
if(chunks >= 256)
|
||||
ranges = malloc((chunks + 1) * 2 * sizeof(unsigned int));
|
||||
else
|
||||
ranges = ranges_static;
|
||||
|
||||
/* Fill ranges list */
|
||||
for(parser = list, i = 0; i < chunks; i++)
|
||||
{
|
||||
char const *comma = strchr(parser, ',');
|
||||
char const *dash = strchr(parser, '-');
|
||||
|
||||
ranges[i * 2] = (dash == parser) ? 0 : atoi(parser);
|
||||
if(dash && (dash + 1 == comma || dash[1] == '\0'))
|
||||
ranges[i * 2 + 1] = ranges[i * 2]; /* special case */
|
||||
else if(dash && (!comma || dash < comma))
|
||||
ranges[i * 2 + 1] = atoi(dash + 1) + 1;
|
||||
else
|
||||
ranges[i * 2 + 1] = ranges[i * 2] + 1;
|
||||
parser = comma + 1;
|
||||
}
|
||||
|
||||
ranges[i * 2] = ranges[i * 2 + 1] = 0;
|
||||
}
|
||||
|
||||
void _zz_setseed(int32_t s)
|
||||
{
|
||||
seed = s;
|
||||
@ -258,6 +299,26 @@ void _zz_register(int fd)
|
||||
#endif
|
||||
files[i].fuzz.uflag = 0;
|
||||
|
||||
/* Check whether we should ignore the fd */
|
||||
if(ranges)
|
||||
{
|
||||
static int idx = 0;
|
||||
int *r;
|
||||
|
||||
idx++;
|
||||
|
||||
for(r = ranges; r[1]; r += 2)
|
||||
if(idx >= r[0] && (r[0] == r[1] || idx < r[1]))
|
||||
goto range_ok;
|
||||
|
||||
files[i].active = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
range_ok:
|
||||
files[i].active = 1;
|
||||
}
|
||||
|
||||
if(autoinc)
|
||||
seed++;
|
||||
|
||||
@ -311,6 +372,14 @@ int _zz_islocked(int fd)
|
||||
return files[fds[fd]].locked;
|
||||
}
|
||||
|
||||
int _zz_isactive(int fd)
|
||||
{
|
||||
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
|
||||
return 1;
|
||||
|
||||
return files[fds[fd]].active;
|
||||
}
|
||||
|
||||
int64_t _zz_getpos(int fd)
|
||||
{
|
||||
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
|
||||
|
||||
1
src/fd.h
1
src/fd.h
@ -32,6 +32,7 @@ extern void _zz_unregister(int);
|
||||
extern void _zz_lock(int);
|
||||
extern void _zz_unlock(int);
|
||||
extern int _zz_islocked(int);
|
||||
extern int _zz_isactive(int);
|
||||
extern int64_t _zz_getpos(int);
|
||||
extern void _zz_setpos(int, int64_t);
|
||||
extern void _zz_addpos(int, int64_t);
|
||||
|
||||
@ -64,6 +64,7 @@ extern void _zz_fuzzing(char const *mode)
|
||||
fuzzing = FUZZING_UNSET;
|
||||
}
|
||||
|
||||
/* This function is the same as _zz_pick() */
|
||||
void _zz_bytes(char const *list)
|
||||
{
|
||||
char const *parser;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
extern void _zz_fuzzing(char const *);
|
||||
extern void _zz_bytes(char const *);
|
||||
extern void _zz_pick(char const *);
|
||||
extern void _zz_protect(char const *);
|
||||
extern void _zz_refuse(char const *);
|
||||
|
||||
|
||||
22
src/lib-fd.c
22
src/lib-fd.c
@ -207,7 +207,7 @@ RECV_T NEW(recv)(int s, void *buf, size_t len, int flags)
|
||||
|
||||
LOADSYM(recv);
|
||||
ret = ORIG(recv)(s, buf, len, flags);
|
||||
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s))
|
||||
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s) || !_zz_isactive(s))
|
||||
return ret;
|
||||
|
||||
if(ret > 0)
|
||||
@ -240,7 +240,7 @@ RECV_T NEW(recvfrom)(int s, void *buf, size_t len, int flags,
|
||||
|
||||
LOADSYM(recvfrom);
|
||||
ret = ORIG(recvfrom)(s, buf, len, flags, from, fromlen);
|
||||
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s))
|
||||
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s) || !_zz_isactive(s))
|
||||
return ret;
|
||||
|
||||
if(ret > 0)
|
||||
@ -273,7 +273,7 @@ RECV_T NEW(recvmsg)(int s, struct msghdr *hdr, int flags)
|
||||
|
||||
LOADSYM(recvmsg);
|
||||
ret = ORIG(recvmsg)(s, hdr, flags);
|
||||
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s))
|
||||
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s) || !_zz_isactive(s))
|
||||
return ret;
|
||||
|
||||
fuzz_iovec(s, hdr->msg_iov, ret);
|
||||
@ -293,7 +293,8 @@ int NEW(read)(int fd, void *buf, unsigned int count)
|
||||
|
||||
LOADSYM(read);
|
||||
ret = ORIG(read)(fd, buf, count);
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|
||||
|| !_zz_isactive(fd))
|
||||
return ret;
|
||||
|
||||
if(ret > 0)
|
||||
@ -324,7 +325,8 @@ ssize_t NEW(readv)(int fd, const struct iovec *iov, int count)
|
||||
|
||||
LOADSYM(readv);
|
||||
ret = ORIG(readv)(fd, iov, count);
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|
||||
|| !_zz_isactive(fd))
|
||||
return ret;
|
||||
|
||||
fuzz_iovec(fd, iov, ret);
|
||||
@ -342,7 +344,8 @@ ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset)
|
||||
|
||||
LOADSYM(pread);
|
||||
ret = ORIG(pread)(fd, buf, count, offset);
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|
||||
|| !_zz_isactive(fd))
|
||||
return ret;
|
||||
|
||||
if(ret > 0)
|
||||
@ -375,7 +378,8 @@ ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset)
|
||||
{ \
|
||||
LOADSYM(fn); \
|
||||
ret = ORIG(fn)(fd, offset, whence); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)) \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
|
||||
|| !_zz_isactive(fd)) \
|
||||
return ret; \
|
||||
debug("%s(%i, %lli, %i) = %lli", __func__, fd, \
|
||||
(long long int)offset, whence, (long long int)ret); \
|
||||
@ -406,7 +410,7 @@ int NEW(aio_read)(struct aiocb *aiocbp)
|
||||
int fd = aiocbp->aio_fildes;
|
||||
|
||||
LOADSYM(aio_read);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(aio_read)(aiocbp);
|
||||
|
||||
_zz_lock(fd);
|
||||
@ -425,7 +429,7 @@ ssize_t NEW(aio_return)(struct aiocb *aiocbp)
|
||||
int fd = aiocbp->aio_fildes;
|
||||
|
||||
LOADSYM(aio_return);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(aio_return)(aiocbp);
|
||||
|
||||
ret = ORIG(aio_return)(aiocbp);
|
||||
|
||||
@ -223,7 +223,8 @@ int nbmaps = 0;
|
||||
do { \
|
||||
char *b = MAP_FAILED; \
|
||||
LOADSYM(fn); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)) \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
|
||||
|| !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(start, length, prot, flags, fd, offset); \
|
||||
ret = ORIG(fn)(NULL, length, prot, flags, fd, offset); \
|
||||
if(ret != MAP_FAILED && length) \
|
||||
@ -317,7 +318,8 @@ kern_return_t NEW(map_fd)(int fd, vm_offset_t offset, vm_offset_t *addr,
|
||||
|
||||
LOADSYM(map_fd);
|
||||
ret = ORIG(map_fd)(fd, offset, addr, find_space, numbytes);
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|
||||
|| !_zz_isactive(fd))
|
||||
return ret;
|
||||
|
||||
if(ret == 0 && numbytes)
|
||||
|
||||
@ -175,7 +175,7 @@ FILE *NEW(freopen)(const char *path, const char *mode, FILE *stream)
|
||||
int fd; \
|
||||
LOADSYM(fn); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd)) \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(stream, offset, whence); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(stream, offset, whence); \
|
||||
@ -203,7 +203,7 @@ void NEW(rewind)(FILE *stream)
|
||||
|
||||
LOADSYM(rewind);
|
||||
fd = fileno(stream);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
{
|
||||
ORIG(rewind)(stream);
|
||||
return;
|
||||
@ -233,7 +233,7 @@ size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
|
||||
LOADSYM(fread);
|
||||
fd = fileno(stream);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(fread)(ptr, size, nmemb, stream);
|
||||
|
||||
pos = ftell(stream);
|
||||
@ -294,7 +294,7 @@ size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
int fd; \
|
||||
LOADSYM(fn); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd)) \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(stream); \
|
||||
@ -332,7 +332,7 @@ char *NEW(fgets)(char *s, int size, FILE *stream)
|
||||
LOADSYM(fgets);
|
||||
LOADSYM(fgetc);
|
||||
fd = fileno(stream);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(fgets)(s, size, stream);
|
||||
|
||||
#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
|
||||
@ -385,7 +385,7 @@ int NEW(ungetc)(int c, FILE *stream)
|
||||
|
||||
LOADSYM(ungetc);
|
||||
fd = fileno(stream);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(ungetc)(c, stream);
|
||||
|
||||
_zz_lock(fd);
|
||||
@ -439,7 +439,7 @@ int NEW(fclose)(FILE *fp)
|
||||
LOADSYM(getdelim); \
|
||||
LOADSYM(fgetc); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd)) \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(getdelim)(lineptr, n, delim, stream); \
|
||||
line = *lineptr; \
|
||||
size = line ? *n : 0; \
|
||||
@ -521,7 +521,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
LOADSYM(fgetln);
|
||||
LOADSYM(fgetc);
|
||||
fd = fileno(stream);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(fgetln)(stream, len);
|
||||
|
||||
#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
|
||||
@ -570,7 +570,7 @@ int NEW(__srefill)(FILE *fp)
|
||||
|
||||
LOADSYM(__srefill);
|
||||
fd = fileno(fp);
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(__srefill)(fp);
|
||||
|
||||
_zz_lock(fd);
|
||||
|
||||
@ -90,6 +90,10 @@ void _zz_init(void)
|
||||
if(tmp && *tmp)
|
||||
_zz_bytes(tmp);
|
||||
|
||||
tmp = getenv("ZZUF_PICK");
|
||||
if(tmp && *tmp)
|
||||
_zz_pick(tmp);
|
||||
|
||||
tmp = getenv("ZZUF_PROTECT");
|
||||
if(tmp && *tmp)
|
||||
_zz_protect(tmp);
|
||||
|
||||
@ -33,7 +33,8 @@
|
||||
|
||||
void _zz_opts_init(struct opts *opts)
|
||||
{
|
||||
opts->fuzzing = opts->bytes = opts->protect = opts->refuse = NULL;
|
||||
opts->fuzzing = opts->bytes = opts->pick = NULL;
|
||||
opts->protect = opts->refuse = NULL;
|
||||
opts->seed = DEFAULT_SEED;
|
||||
opts->endseed = DEFAULT_SEED + 1;
|
||||
opts->minratio = opts->maxratio = DEFAULT_RATIO;
|
||||
|
||||
@ -20,7 +20,7 @@ struct opts
|
||||
{
|
||||
char **oldargv;
|
||||
char **newargv;
|
||||
char *fuzzing, *bytes, *protect, *refuse;
|
||||
char *fuzzing, *bytes, *pick, *protect, *refuse;
|
||||
uint32_t seed;
|
||||
uint32_t endseed;
|
||||
double minratio;
|
||||
|
||||
16
src/zzuf.c
16
src/zzuf.c
@ -157,7 +157,7 @@ int main(int argc, char *argv[])
|
||||
# define OPTSTR_RLIMIT ""
|
||||
#endif
|
||||
#define OPTSTR OPTSTR_REGEX OPTSTR_RLIMIT \
|
||||
"Ab:B:C:dD:f:F:imnP:qr:R:s:ST:vxhV"
|
||||
"Ab:B:C:dD:f:F:imnp:P:qr:R:s:ST:vxhV"
|
||||
#define MOREINFO "Try `%s --help' for more information.\n"
|
||||
int option_index = 0;
|
||||
static struct myoption long_options[] =
|
||||
@ -184,6 +184,7 @@ int main(int argc, char *argv[])
|
||||
{ "md5", 0, NULL, 'm' },
|
||||
{ "max-memory", 1, NULL, 'M' },
|
||||
{ "network", 0, NULL, 'n' },
|
||||
{ "pick", 1, NULL, 'p' },
|
||||
{ "protect", 1, NULL, 'P' },
|
||||
{ "quiet", 0, NULL, 'q' },
|
||||
{ "ratio", 1, NULL, 'r' },
|
||||
@ -274,6 +275,9 @@ int main(int argc, char *argv[])
|
||||
case 'n': /* --network */
|
||||
setenv("ZZUF_NETWORK", "1", 1);
|
||||
break;
|
||||
case 'p': /* --pick */
|
||||
opts->pick = myoptarg;
|
||||
break;
|
||||
case 'P': /* --protect */
|
||||
opts->protect = myoptarg;
|
||||
break;
|
||||
@ -375,6 +379,8 @@ int main(int argc, char *argv[])
|
||||
setenv("ZZUF_FUZZING", opts->fuzzing, 1);
|
||||
if(opts->bytes)
|
||||
setenv("ZZUF_BYTES", opts->bytes, 1);
|
||||
if(opts->pick)
|
||||
setenv("ZZUF_PICK", opts->pick, 1);
|
||||
if(opts->protect)
|
||||
setenv("ZZUF_PROTECT", opts->protect, 1);
|
||||
if(opts->refuse)
|
||||
@ -427,6 +433,8 @@ static void loop_stdin(struct opts *opts)
|
||||
_zz_fuzzing(opts->fuzzing);
|
||||
if(opts->bytes)
|
||||
_zz_bytes(opts->bytes);
|
||||
if(opts->pick)
|
||||
_zz_pick(opts->pick);
|
||||
if(opts->protect)
|
||||
_zz_protect(opts->protect);
|
||||
if(opts->refuse)
|
||||
@ -1085,9 +1093,10 @@ static void usage(void)
|
||||
printf(" [-T seconds] [-b ranges] [-P protect] [-R refuse]\n");
|
||||
#endif
|
||||
#if defined HAVE_REGEX_H
|
||||
printf(" [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n");
|
||||
#else
|
||||
printf(" [-p descriptors] [-I include] [-E exclude]\n");
|
||||
printf(" [PROGRAM [--] [ARGS]...]\n");
|
||||
#else
|
||||
printf(" [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n");
|
||||
#endif
|
||||
printf(" zzuf -h | --help\n");
|
||||
printf(" zzuf -V | --version\n");
|
||||
@ -1117,6 +1126,7 @@ static void usage(void)
|
||||
printf(" -M, --max-memory <n> maximum child virtual memory size in MB\n");
|
||||
#endif
|
||||
printf(" -n, --network fuzz network input\n");
|
||||
printf(" -p, --pick <list> only fuzz Nth descriptor with N in <list>\n");
|
||||
printf(" -P, --protect <list> protect bytes and characters in <list>\n");
|
||||
printf(" -q, --quiet do not print children's messages\n");
|
||||
printf(" -r, --ratio <ratio> bit fuzzing ratio (default %g)\n", DEFAULT_RATIO);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user