* Implemented --max-crashes.
* Renamed --forks to --max-forks. * Changed debug messages format.
This commit is contained in:
parent
1322fd8cf0
commit
31993f9bc7
21
doc/zzuf.1
21
doc/zzuf.1
@ -4,7 +4,7 @@ zzuf \- multiple purpose fuzzer
|
||||
.SH SYNOPSIS
|
||||
\fBzzuf\fR [\fB\-cdinqS\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR | \fB\-s\fR \fIstart:stop\fR]
|
||||
.br
|
||||
[\fB\-F\fR \fIchildren\fR] [\fB\-B\fR \fIbytes\fR] [\fB\-T\fR \fIseconds\fR]
|
||||
[\fB\-F\fR \fIforks\fR] [\fB\-C\fR \fIcrashes\fR] [\fB\-B\fR \fIbytes\fR] [\fB\-T\fR \fIseconds\fR]
|
||||
.br
|
||||
[\fB\-P\fR \fIlist\fR] [\fB\-R\fR \fIlist\fR]
|
||||
.br
|
||||
@ -51,6 +51,15 @@ has the same effect as
|
||||
See the \fB\-I\fR flag for more information on restricting fuzzing to
|
||||
specific files.
|
||||
.TP
|
||||
\fB\-C\fR, \fB\-\-max\-crashes\fR=\fIn\fR
|
||||
Stop forking when at least \fIn\fR children have crashed. The default value
|
||||
is 1, meaning \fBzzuf\fR will stop as soon as one child has crashed. A process
|
||||
is considered to have crashed if any signal (such as, but not limited to,
|
||||
\fBSIGSEGV\fR) caused it to exit.
|
||||
|
||||
This option is only relevant if the \fB\-s\fR flag is used with an interval
|
||||
argument.
|
||||
.TP
|
||||
\fB\-d\fR, \fB\-\-debug\fR
|
||||
Activate the display of debug messages.
|
||||
.TP
|
||||
@ -63,9 +72,11 @@ and do not want it to fuzz files in the \fB/etc\fR directory.
|
||||
Multiple \fB\-E\fR flags can be specified, in which case files matching any one
|
||||
of the regular expressions will be ignored.
|
||||
.TP
|
||||
\fB\-F\fR, \fB\-\-max-forks\fR=\fIchildren\fR
|
||||
Specify the number of simultaneous children that can be run. This option is
|
||||
only useful if the \fB\-s\fR flag is used with an interval argument.
|
||||
\fB\-F\fR, \fB\-\-max-forks\fR=\fIforks\fR
|
||||
Specify the number of simultaneous children that can be run.
|
||||
|
||||
This option is only relevant if the \fB\-s\fR flag is used with an interval
|
||||
argument.
|
||||
.TP
|
||||
\fB\-i\fR, \fB\-\-stdin\fR
|
||||
Fuzz the application's standard input. By default \fBzzuf\fR only fuzzes files.
|
||||
@ -211,7 +222,7 @@ launching up to three simultaneous child processes (\fB\-F\ 3\fR), killing
|
||||
\fBMPlayer\fR if it takes more than one minute to read the file (\fB\-T\ 60\fR)
|
||||
and disabling its \fBSIGSEGV\fR signal handler (\fB\-S\fR):
|
||||
.PP
|
||||
\fB zzuf -c -q -s 0:10000 -F 3 -T 60 -r 0.02 \\\fR
|
||||
\fB zzuf -c -r 0.02 -q -s 0:10000 -F 3 -T 60 -S \\\fR
|
||||
\fB mplayer -- -benchmark -vo null -fps 1000 movie.avi\fR
|
||||
.SH RESTRICTIONS
|
||||
.PP
|
||||
|
||||
92
src/zzuf.c
92
src/zzuf.c
@ -31,7 +31,6 @@
|
||||
#include <unistd.h>
|
||||
#include <regex.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@ -68,7 +67,7 @@ static struct child_list
|
||||
int bytes, seed;
|
||||
time_t date;
|
||||
} *child_list;
|
||||
static int parallel = 1, child_count = 0;
|
||||
static int maxforks = 1, child_count = 0, maxcrashes = 1, crashes = 0;
|
||||
|
||||
static int seed = 0;
|
||||
static int endseed = 1;
|
||||
@ -102,29 +101,30 @@ int main(int argc, char *argv[])
|
||||
static struct option long_options[] =
|
||||
{
|
||||
/* Long option, needs arg, flag, short option */
|
||||
{ "max-bytes", 1, NULL, 'B' },
|
||||
{ "cmdline", 0, NULL, 'c' },
|
||||
{ "debug", 0, NULL, 'd' },
|
||||
{ "exclude", 1, NULL, 'E' },
|
||||
{ "max-forks", 1, NULL, 'F' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "stdin", 0, NULL, 'i' },
|
||||
{ "include", 1, NULL, 'I' },
|
||||
{ "network", 0, NULL, 'n' },
|
||||
{ "protect", 1, NULL, 'P' },
|
||||
{ "quiet", 0, NULL, 'q' },
|
||||
{ "ratio", 1, NULL, 'r' },
|
||||
{ "refuse", 1, NULL, 'R' },
|
||||
{ "seed", 1, NULL, 's' },
|
||||
{ "signal", 0, NULL, 'S' },
|
||||
{ "max-time", 1, NULL, 'T' },
|
||||
{ "version", 0, NULL, 'v' },
|
||||
{ "max-bytes", 1, NULL, 'B' },
|
||||
{ "cmdline", 0, NULL, 'c' },
|
||||
{ "max-crashes", 1, NULL, 'C' },
|
||||
{ "debug", 0, NULL, 'd' },
|
||||
{ "exclude", 1, NULL, 'E' },
|
||||
{ "max-forks", 1, NULL, 'F' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "stdin", 0, NULL, 'i' },
|
||||
{ "include", 1, NULL, 'I' },
|
||||
{ "network", 0, NULL, 'n' },
|
||||
{ "protect", 1, NULL, 'P' },
|
||||
{ "quiet", 0, NULL, 'q' },
|
||||
{ "ratio", 1, NULL, 'r' },
|
||||
{ "refuse", 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:nP:qr:R:s:ST:v",
|
||||
int c = getopt_long(argc, argv, "B:cC:dE:F:hiI:nP:qr:R: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:nP:qr:R:s:ST:v");
|
||||
int c = getopt(argc, argv, "B:cC:dE:F:hiI:nP:qr:R:s:ST:v");
|
||||
# endif
|
||||
if(c == -1)
|
||||
break;
|
||||
@ -165,7 +165,7 @@ int main(int argc, char *argv[])
|
||||
setenv("ZZUF_RATIO", optarg, 1);
|
||||
break;
|
||||
case 'F': /* --max-forks */
|
||||
parallel = atoi(optarg) > 1 ? atoi(optarg) : 1;
|
||||
maxforks = atoi(optarg) > 1 ? atoi(optarg) : 1;
|
||||
break;
|
||||
case 'B': /* --max-bytes */
|
||||
maxbytes = atoi(optarg);
|
||||
@ -173,6 +173,11 @@ int main(int argc, char *argv[])
|
||||
case 'T': /* --max-time */
|
||||
maxtime = atof(optarg);
|
||||
break;
|
||||
case 'C': /* --max-crashes */
|
||||
maxcrashes = atoi(optarg);
|
||||
if(maxcrashes <= 0)
|
||||
maxcrashes = 0;
|
||||
break;
|
||||
case 'P': /* --protect */
|
||||
setenv("ZZUF_PROTECT", optarg, 1);
|
||||
break;
|
||||
@ -233,8 +238,8 @@ int main(int argc, char *argv[])
|
||||
setenv("ZZUF_EXCLUDE", exclude, 1);
|
||||
|
||||
/* Allocate memory for children handling */
|
||||
child_list = malloc(parallel * sizeof(struct child_list));
|
||||
for(i = 0; i < parallel; i++)
|
||||
child_list = malloc(maxforks * sizeof(struct child_list));
|
||||
for(i = 0; i < maxforks; i++)
|
||||
child_list[i].status = STATUS_FREE;
|
||||
child_count = 0;
|
||||
|
||||
@ -246,14 +251,12 @@ int main(int argc, char *argv[])
|
||||
memcpy(newargv, argv + optind, (argc - optind) * sizeof(char *));
|
||||
newargv[argc - optind] = (char *)NULL;
|
||||
|
||||
/* Handle children in our way */
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
|
||||
/* Main loop */
|
||||
while(child_count || seed < endseed)
|
||||
{
|
||||
/* Spawn one new child, if necessary */
|
||||
if(child_count < parallel && seed < endseed)
|
||||
if(child_count < maxforks && seed < endseed &&
|
||||
(maxcrashes && crashes < maxcrashes))
|
||||
spawn_child(newargv);
|
||||
|
||||
/* Cleanup dead or dying children */
|
||||
@ -261,6 +264,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Read data from children */
|
||||
read_children();
|
||||
|
||||
if(maxcrashes && crashes >= maxcrashes && child_count == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
@ -323,7 +329,7 @@ static void spawn_child(char **argv)
|
||||
int i, j;
|
||||
|
||||
/* Find an empty slot */
|
||||
for(i = 0; i < parallel; i++)
|
||||
for(i = 0; i < maxforks; i++)
|
||||
if(child_list[i].status == STATUS_FREE)
|
||||
break;
|
||||
|
||||
@ -386,12 +392,12 @@ static void clean_children(void)
|
||||
int i, j;
|
||||
|
||||
/* Terminate children if necessary */
|
||||
for(i = 0; i < parallel; i++)
|
||||
for(i = 0; i < maxforks; i++)
|
||||
{
|
||||
if(child_list[i].status == STATUS_RUNNING
|
||||
&& maxbytes >= 0 && child_list[i].bytes > maxbytes)
|
||||
{
|
||||
fprintf(stdout, "seed %i: data exceeded, sending SIGTERM\n",
|
||||
fprintf(stdout, "zzuf[seed=%i]: data exceeded, sending SIGTERM\n",
|
||||
child_list[i].seed);
|
||||
kill(child_list[i].pid, SIGTERM);
|
||||
child_list[i].date = now;
|
||||
@ -402,7 +408,7 @@ static void clean_children(void)
|
||||
&& maxtime >= 0.0
|
||||
&& difftime(now, child_list[i].date) > maxtime)
|
||||
{
|
||||
fprintf(stdout, "seed %i: time exceeded, sending SIGTERM\n",
|
||||
fprintf(stdout, "zzuf[seed=%i]: time exceeded, sending SIGTERM\n",
|
||||
child_list[i].seed);
|
||||
kill(child_list[i].pid, SIGTERM);
|
||||
child_list[i].date = now;
|
||||
@ -411,12 +417,12 @@ static void clean_children(void)
|
||||
}
|
||||
|
||||
/* Kill children if necessary */
|
||||
for(i = 0; i < parallel; i++)
|
||||
for(i = 0; i < maxforks; i++)
|
||||
{
|
||||
if(child_list[i].status == STATUS_SIGTERM
|
||||
&& difftime(now, child_list[i].date) > 2.0)
|
||||
{
|
||||
fprintf(stdout, "seed %i: not responding, sending SIGKILL\n",
|
||||
fprintf(stdout, "zzuf[seed=%i]: not responding, sending SIGKILL\n",
|
||||
child_list[i].seed);
|
||||
kill(child_list[i].pid, SIGKILL);
|
||||
child_list[i].status = STATUS_SIGKILL;
|
||||
@ -424,7 +430,7 @@ static void clean_children(void)
|
||||
}
|
||||
|
||||
/* Collect dead children */
|
||||
for(i = 0; i < parallel; i++)
|
||||
for(i = 0; i < maxforks; i++)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
@ -439,11 +445,17 @@ static void clean_children(void)
|
||||
continue;
|
||||
|
||||
if(WIFEXITED(status) && WEXITSTATUS(status))
|
||||
fprintf(stdout, "seed %i: exit %i\n",
|
||||
{
|
||||
fprintf(stdout, "zzuf[seed=%i]: exit %i\n",
|
||||
child_list[i].seed, WEXITSTATUS(status));
|
||||
crashes++;
|
||||
}
|
||||
else if(WIFSIGNALED(status))
|
||||
fprintf(stdout, "seed %i: signal %i\n",
|
||||
{
|
||||
fprintf(stdout, "zzuf[seed=%i]: signal %i\n",
|
||||
child_list[i].seed, WTERMSIG(status));
|
||||
crashes++;
|
||||
}
|
||||
|
||||
for(j = 0; j < 3; j++)
|
||||
if(child_list[i].fd[j] >= 0)
|
||||
@ -464,7 +476,7 @@ static void read_children(void)
|
||||
|
||||
/* Read data from all sockets */
|
||||
FD_ZERO(&fdset);
|
||||
for(i = 0; i < parallel; i++)
|
||||
for(i = 0; i < maxforks; i++)
|
||||
{
|
||||
if(child_list[i].status != STATUS_RUNNING)
|
||||
continue;
|
||||
@ -482,7 +494,7 @@ static void read_children(void)
|
||||
return;
|
||||
|
||||
/* XXX: cute (i, j) iterating hack */
|
||||
for(i = 0, j = 0; i < parallel; i += (j == 2), j = (j + 1) % 3)
|
||||
for(i = 0, j = 0; i < maxforks; i += (j == 2), j = (j + 1) % 3)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
|
||||
@ -554,7 +566,7 @@ static void version(void)
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: zzuf [ -cdinqS ] [ -r ratio ] [ -s seed | -s start:stop ]\n");
|
||||
printf(" [ -F children ] [ -B bytes ] [ -T seconds ]\n");
|
||||
printf(" [ -F forks ] [ -C crashes ] [ -B bytes ] [ -T seconds ]\n");
|
||||
printf(" [ -P protect ] [ -R refuse ]\n");
|
||||
printf(" [ -I include ] [ -E exclude ] COMMAND [ARGS]...\n");
|
||||
printf(" zzuf -h\n");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user