* Implemented signal handling.

* Updated documentation accordingly and improved a few parts.
This commit is contained in:
Sam Hocevar
2007-01-01 21:35:54 +00:00
committed by sam
parent 85f6af7cb2
commit c8df6d0f5b
7 changed files with 214 additions and 26 deletions

View File

@@ -4,7 +4,7 @@ zzuf \- multiple purpose fuzzer
.SH SYNOPSIS
.B zzuf
[
.B \-vqdhic
.B \-cdhiqSv
] [
.B \-r
.I ratio
@@ -86,8 +86,8 @@ Do not fuzz files whose name matches the
.B <regex>
regular expression. This option supersedes anything that is specified by the
.B \-\-exclude
flag. Use this for instance if you do not know for sure what files your
application is going to read, but do not want it to fuzz files in the
flag. Use this for instance if you are unsure of what files your
application is going to read and do not want it to fuzz files in the
.B /etc
directory.
@@ -119,11 +119,14 @@ configuration files at startup and you only want specific files to be fuzzed.
Multiple
.B \-I
flags can be specified, in which case files matching any one of the regular
expressions will be fuzzed.
expressions will be fuzzed. See also the
.B \-c
flag.
.TP
.B \-q, \-\-quiet
Hide the output of the fuzzed application. This is useful if the application
is very verbose but only its exit code is really useful to you.
is very verbose but only its exit code or signaled status is really useful to
you.
.TP
.B \-r, \-\-ratio <ratio>
Specify the amount of bits that will be randomly fuzzed. A value of 0
@@ -153,6 +156,27 @@ If an interval is specified,
will run the application several times, each time with a different seed, and
report the behaviour of each run.
.TP
.B \-S, \-\-signal
Prevent children from installing signal handlers for signals that usually
cause coredumps. These signals are
.BR SIGABRT ,
.BR SIGFPE ,
.BR SIGILL ,
.BR SIGQUIT ,
.BR SIGSEGV ,
.B SIGTRAP
and, if available on the running platform,
.BR SIGSYS ,
.BR SIGEMT ,
.BR SIGBUS ,
.B SIGXCPU
and
.BR SIGXFSZ .
Instead of calling the signal handler, the application will simply crash. If
you do not want core dumps, you should set appropriate limits with the
.B limit coredumpsize
command. See your shell's documentation on how to set such limits.
.TP
.B \-T, \-\-max\-time <n>
Automatically terminate child processes that run for more than
.B <n>
@@ -187,7 +211,7 @@ as the original input and excluding
.B .xml
files from fuzzing (because
.B convert
will also open its own configuration files and we do not want
will also open its own XML configuration files and we do not want
.B zzuf
to fuzz them):
.nf
@@ -215,12 +239,28 @@ to reproduce the same behaviour without using
.B % vlc fuzzy-movie.avi
.fi
Fuzz
Fuzz 2% of
.BR mplayer 's
input with seeds 0 to 9999, launching up to 3 simultaneous child processes
and killing
.BR mplayer
if it takes more than one minute to read the file:
input bits
.RB ( \-r
.BR 0.02 )
with seeds 0 to 9999
.RB ( \-s
.BR 0:10000 ),
disabling its standard output messages
.RB ( \-q ),
launching up to three simultaneous child processes
.RB ( \-F
.BR 3 ),
killing
.B mplayer
if it takes more than one minute to read the file
.RB ( \-T
.BR 60 )
and disabling its
.B SIGSEGV
signal handler
.RB ( \-S ):
.fn
.B % zzuf -c -q -s 0:10000 -F 3 -T 60 -r 0.02 mplayer movie.avi -- -benchmark -vo null -fps 1000
@@ -239,6 +279,14 @@ etc. One important unimplemented function is
Network fuzzing is not implemented. It is not yet possible to insert or
drop bytes from the input, to fuzz according to the file format, or to do
all these complicated operations. They are planned, though.
Due to
.B zzuf
using
.B LD_PRELOAD
to run its child processes, it will fail in the presence of any mechanism
that disables preloading. For instance setuid root binaries will not be
fuzzed.
.RI
.SH AUTHOR
.B Zzuf

View File

@@ -5,7 +5,8 @@ zzuf_CPPFLAGS = -DLIBDIR=\"$(libdir)/zzuf\"
pkglib_LTLIBRARIES = libzzuf.la
libzzuf_la_SOURCES = libzzuf.c libzzuf.h fuzz.c fuzz.h debug.c debug.h \
load-fd.c load-stream.c load.h random.c random.h
load-fd.c load-signal.c load-stream.c load.h \
random.c random.h
libzzuf_la_LDFLAGS = -module -avoid-version -no-undefined
libzzuf_la_LIBADD = -ldl

View File

@@ -40,8 +40,9 @@
/* Global variables */
int _zz_ready = 0;
int _zz_hasdebug = 0;
int _zz_seed = 0;
float _zz_ratio = 0.004f;
int _zz_seed = 0;
int _zz_signal = 0;
/* Local variables */
static regex_t * re_include = NULL;
@@ -57,7 +58,7 @@ void _zz_init(void)
char *tmp;
tmp = getenv("ZZUF_DEBUG");
if(tmp && *tmp)
if(tmp && *tmp == '1')
_zz_hasdebug = 1;
tmp = getenv("ZZUF_SEED");
@@ -86,6 +87,10 @@ void _zz_init(void)
regcomp(re_exclude, tmp, REG_EXTENDED);
}
tmp = getenv("ZZUF_SIGNAL");
if(tmp && *tmp == '1')
_zz_signal = 1;
_zz_fd_init();
tmp = getenv("ZZUF_STDIN");
@@ -93,6 +98,7 @@ void _zz_init(void)
_zz_register(0);
_zz_load_fd();
_zz_load_signal();
_zz_load_stream();
_zz_ready = 1;

View File

@@ -31,8 +31,9 @@ struct fuzz
/* Internal variables */
extern int _zz_ready;
extern int _zz_hasdebug;
extern int _zz_seed;
extern float _zz_ratio;
extern int _zz_seed;
extern int _zz_signal;
/* Library initialisation shit */
extern void _zz_init(void) __attribute__((constructor));

125
src/load-signal.c Normal file
View File

@@ -0,0 +1,125 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
* All Rights Reserved
*
* $Id$
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
* load-signal.c: loaded signal functions
*/
#include "config.h"
/* needed for sighandler_t */
#define _GNU_SOURCE
#if defined HAVE_STDINT_H
# include <stdint.h>
#elif defined HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <signal.h>
#include "libzzuf.h"
#include "debug.h"
#include "fuzz.h"
#include "load.h"
/* Library functions that we divert */
static sighandler_t (*signal_orig) (int signum, sighandler_t handler);
static int (*sigaction_orig) (int signum, const struct sigaction *act,
struct sigaction *oldact);
/* Local functions */
static int isfatal(int signum);
void _zz_load_signal(void)
{
LOADSYM(signal);
LOADSYM(sigaction);
}
static int isfatal(int signum)
{
switch(signum)
{
case SIGABRT:
case SIGFPE:
case SIGILL:
case SIGQUIT:
case SIGSEGV:
case SIGTRAP:
#ifdef SIGSYS
case SIGSYS:
#endif
#ifdef SIGEMT
case SIGEMT:
#endif
#ifdef SIGBUS
case SIGBUS:
#endif
#ifdef SIGXCPU
case SIGXCPU:
#endif
#ifdef SIGXFSZ
case SIGXFSZ:
#endif
return 1;
default:
return 0;
}
}
sighandler_t signal(int signum, sighandler_t handler)
{
sighandler_t ret;
if(!_zz_ready)
LOADSYM(signal);
if(!_zz_signal)
return signal_orig(signum, handler);
ret = signal_orig(signum, isfatal(signum) ? SIG_DFL : handler);
debug("signal(%i, %p) = %p", signum, handler, ret);
return ret;
}
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
int ret;
if(!_zz_ready)
LOADSYM(sigaction);
if(!_zz_signal)
return sigaction_orig(signum, act, oldact);
if(act && isfatal(signum))
{
struct sigaction newact;
memcpy(&newact, act, sizeof(struct sigaction));
newact.sa_handler = SIG_DFL;
ret = sigaction_orig(signum, &newact, oldact);
}
else
ret = sigaction_orig(signum, act, oldact);
debug("sigaction(%i, %p, %p) = %i", signum, act, oldact, ret);
return ret;
}

View File

@@ -27,5 +27,6 @@
} while(0)
extern void _zz_load_fd(void);
extern void _zz_load_signal(void);
extern void _zz_load_stream(void);

View File

@@ -96,25 +96,26 @@ int main(int argc, char *argv[])
static struct option long_options[] =
{
/* Long option, needs arg, flag, short option */
{ "include", 1, NULL, 'I' },
{ "exclude", 1, NULL, 'E' },
{ "cmdline", 0, NULL, 'c' },
{ "stdin", 0, NULL, 'i' },
{ "seed", 1, NULL, 's' },
{ "ratio", 1, NULL, 'r' },
{ "fork", 1, NULL, 'F' },
{ "max-bytes", 1, NULL, 'B' },
{ "max-time", 1, NULL, 'T' },
{ "quiet", 0, NULL, 'q' },
{ "cmdline", 0, NULL, 'c' },
{ "debug", 0, NULL, 'd' },
{ "exclude", 1, NULL, 'E' },
{ "fork", 1, NULL, 'F' },
{ "help", 0, NULL, 'h' },
{ "stdin", 0, NULL, 'i' },
{ "include", 1, NULL, 'I' },
{ "quiet", 0, NULL, 'q' },
{ "ratio", 1, NULL, 'r' },
{ "seed", 1, NULL, 's' },
{ "signal", 0, NULL, 'S' },
{ "max-time", 1, NULL, 'T' },
{ "version", 0, NULL, 'v' },
};
int c = getopt_long(argc, argv, "B:cdE:F:hiI:qr:s:T:v",
int c = getopt_long(argc, argv, "B:cdE:F:hiI:qr:s:ST:v",
long_options, &option_index);
# else
# define MOREINFO "Try `%s -h' for more information.\n"
int c = getopt(argc, argv, "B:cdE:F:hiI:qr:s:T:v");
int c = getopt(argc, argv, "B:cdE:F:hiI:qr:s:ST:v");
# endif
if(c == -1)
break;
@@ -163,6 +164,9 @@ int main(int argc, char *argv[])
case 'q': /* --quiet */
quiet = 1;
break;
case 'S': /* --signal */
setenv("ZZUF_SIGNAL", "1", 1);
break;
case 'd': /* --debug */
setenv("ZZUF_DEBUG", "1", 1);
break;
@@ -528,6 +532,7 @@ static void usage(void)
printf(" -r, --ratio <ratio> bit fuzzing ratio (default 0.004)\n");
printf(" -s, --seed <seed> random seed (default 0)\n");
printf(" --seed <start:stop> specify a seed range\n");
printf(" -S, --signal prevent children from diverting crashing signals\n");
printf(" -T, --max-time <n> kill children that run for more than <n> seconds\n");
printf(" -v, --version output version information and exit\n");
# else
@@ -543,6 +548,7 @@ static void usage(void)
printf(" -r <ratio> bit fuzzing ratio (default 0.004)\n");
printf(" -s <seed> random seed (default 0)\n");
printf(" <start:stop> specify a seed range\n");
printf(" -S prevent children from diverting crashing signals\n");
printf(" -T <n> kill children that run for more than <n> seconds\n");
printf(" -v output version information and exit\n");
# endif