diff --git a/src/fd.c b/src/fd.c index e48c759..06dea45 100644 --- a/src/fd.c +++ b/src/fd.c @@ -43,9 +43,13 @@ static regex_t re_include, re_exclude; static int has_include = 0, has_exclude = 0; #endif +/* Network port cherry picking */ +static int *ports = NULL; +static int static_ports[512]; + /* File descriptor cherry picking */ -static int *ranges = NULL; -static int static_ranges[512]; +static int *list = NULL; +static int static_list[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 @@ -95,10 +99,14 @@ void _zz_exclude(char const *regex) #endif } -/* This function is the same as _zz_bytes() */ -void _zz_pick(char const *list) +void _zz_ports(char const *list) { - ranges = _zz_allocrange(list, static_ranges); + ports = _zz_allocrange(list, static_ports); +} + +void _zz_list(char const *list) +{ + list = _zz_allocrange(list, static_list); } void _zz_setseed(int32_t s) @@ -189,8 +197,10 @@ void _zz_fd_fini(void) free(files); if(fds != static_fds) free(fds); - if(ranges != static_ranges) - free(ranges); + if(list != static_list) + free(list); + if(ports != static_ports) + free(ports); } int _zz_mustwatch(char const *file) @@ -216,6 +226,11 @@ int _zz_iswatched(int fd) return 1; } +int _zz_portwatched(int port) +{ + return _zz_isinrange(port, ports); +} + void _zz_register(int fd) { int i; @@ -273,11 +288,11 @@ void _zz_register(int fd) files[i].fuzz.uflag = 0; /* Check whether we should ignore the fd */ - if(ranges) + if(list) { static int idx = 0; - files[i].active = _zz_isinrange(++idx, ranges); + files[i].active = _zz_isinrange(++idx, list); } else files[i].active = 1; diff --git a/src/fd.h b/src/fd.h index 3e89a13..af25eda 100644 --- a/src/fd.h +++ b/src/fd.h @@ -26,6 +26,7 @@ extern void _zz_fd_init(void); extern void _zz_fd_fini(void); extern int _zz_mustwatch(char const *); +extern int _zz_portwatched(int); extern int _zz_iswatched(int); extern void _zz_register(int); extern void _zz_unregister(int); diff --git a/src/fuzz.c b/src/fuzz.c index 812746f..137150c 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -65,7 +65,6 @@ extern void _zz_fuzzing(char const *mode) fuzzing = FUZZING_UNSET; } -/* This function is the same as _zz_pick() */ void _zz_bytes(char const *list) { /* TODO: free(ranges) if ranges != static_ranges */ diff --git a/src/fuzz.h b/src/fuzz.h index e17b6b5..f15c740 100644 --- a/src/fuzz.h +++ b/src/fuzz.h @@ -18,7 +18,8 @@ extern void _zz_fuzzing(char const *); extern void _zz_bytes(char const *); -extern void _zz_pick(char const *); +extern void _zz_list(char const *); +extern void _zz_ports(char const *); extern void _zz_protect(char const *); extern void _zz_refuse(char const *); diff --git a/src/lib-fd.c b/src/lib-fd.c index 116001e..ea34fda 100644 --- a/src/lib-fd.c +++ b/src/lib-fd.c @@ -43,6 +43,9 @@ #if defined HAVE_SYS_SOCKET_H # include #endif +#if defined HAVE_NETINET_IN_H +# include +#endif #if defined HAVE_SYS_UIO_H # include #endif @@ -171,7 +174,8 @@ int NEW(accept)(int sockfd, struct sockaddr *addr, SOCKLEN_T *addrlen) LOADSYM(accept); ret = ORIG(accept)(sockfd, addr, addrlen); - if(!_zz_ready || _zz_islocked(-1) || !_zz_network) + if(!_zz_ready || _zz_islocked(-1) || !_zz_network + || !_zz_iswatched(sockfd) || !_zz_isactive(sockfd)) return ret; if(ret >= 0) @@ -197,9 +201,32 @@ int NEW(bind)(int sockfd, const struct sockaddr *my_addr, SOCKLEN_T addrlen) if(ret >= 0) { + const struct sockaddr_in* in = (const struct sockaddr_in *)my_addr; + long int port; + + switch(my_addr->sa_family) + { + case AF_INET: +#if defined AF_INET6 + case AF_INET6: +#endif +#if defined AF_UNIX + case AF_UNIX: +#endif + case AF_UNSPEC: + port = ntohs(in->sin_port); + if(!_zz_portwatched(port)) + { + _zz_unregister(sockfd); + return ret; + } + break; + default: + break; + } + debug("%s(%i, %p, %i) = %i", __func__, sockfd, my_addr, (int)addrlen, ret); - _zz_register(ret); } return ret; diff --git a/src/libzzuf.c b/src/libzzuf.c index f4e2759..e08b7db 100644 --- a/src/libzzuf.c +++ b/src/libzzuf.c @@ -90,9 +90,13 @@ void _zz_init(void) if(tmp && *tmp) _zz_bytes(tmp); - tmp = getenv("ZZUF_PICK"); + tmp = getenv("ZZUF_LIST"); if(tmp && *tmp) - _zz_pick(tmp); + _zz_list(tmp); + + tmp = getenv("ZZUF_PORTS"); + if(tmp && *tmp) + _zz_ports(tmp); tmp = getenv("ZZUF_PROTECT"); if(tmp && *tmp) diff --git a/src/opts.c b/src/opts.c index 1bc8e12..8d1fe81 100644 --- a/src/opts.c +++ b/src/opts.c @@ -33,7 +33,7 @@ void _zz_opts_init(struct opts *opts) { - opts->fuzzing = opts->bytes = opts->pick = NULL; + opts->fuzzing = opts->bytes = opts->list = opts->ports = NULL; opts->protect = opts->refuse = NULL; opts->seed = DEFAULT_SEED; opts->endseed = DEFAULT_SEED + 1; diff --git a/src/opts.h b/src/opts.h index 8a4ed84..7ab05ae 100644 --- a/src/opts.h +++ b/src/opts.h @@ -20,7 +20,7 @@ struct opts { char **oldargv; char **newargv; - char *fuzzing, *bytes, *pick, *protect, *refuse; + char *fuzzing, *bytes, *list, *ports, *protect, *refuse; uint32_t seed; uint32_t endseed; double minratio; diff --git a/src/zzuf.c b/src/zzuf.c index b7e6391..72ca254 100644 --- a/src/zzuf.c +++ b/src/zzuf.c @@ -146,6 +146,7 @@ int main(int argc, char *argv[]) char *include = NULL, *exclude = NULL; int cmdline = 0; #endif + int network = 0; int i; _zz_opts_init(opts); @@ -168,7 +169,7 @@ int main(int argc, char *argv[]) # define OPTSTR_RLIMIT_CPU "" #endif #define OPTSTR OPTSTR_REGEX OPTSTR_RLIMIT_MEM OPTSTR_RLIMIT_CPU \ - "Ab:B:C:dD:f:F:imnp:P:qr:R:s:St:vxhV" + "Ab:B:C:dD:f:F:il:mnp:P:qr:R:s:St:vxhV" #define MOREINFO "Try `%s --help' for more information.\n" int option_index = 0; static struct myoption long_options[] = @@ -192,10 +193,11 @@ int main(int argc, char *argv[]) #if defined HAVE_REGEX_H { "include", 1, NULL, 'I' }, #endif + { "list", 1, NULL, 'l' }, { "md5", 0, NULL, 'm' }, { "max-memory", 1, NULL, 'M' }, { "network", 0, NULL, 'n' }, - { "pick", 1, NULL, 'p' }, + { "ports", 1, NULL, 'p' }, { "protect", 1, NULL, 'P' }, { "quiet", 0, NULL, 'q' }, { "ratio", 1, NULL, 'r' }, @@ -275,6 +277,9 @@ int main(int argc, char *argv[]) } break; #endif + case 'l': /* --list */ + opts->list = myoptarg; + break; case 'm': /* --md5 */ opts->md5 = 1; break; @@ -286,9 +291,10 @@ int main(int argc, char *argv[]) #endif case 'n': /* --network */ setenv("ZZUF_NETWORK", "1", 1); + network = 1; break; - case 'p': /* --pick */ - opts->pick = myoptarg; + case 'p': /* --ports */ + opts->ports = myoptarg; break; case 'P': /* --protect */ opts->protect = myoptarg; @@ -342,6 +348,15 @@ int main(int argc, char *argv[]) } } + if(opts->ports && !network) + { + fprintf(stderr, "%s: port option (-p) requires network fuzzing (-n)\n", + argv[0]); + printf(MOREINFO, argv[0]); + _zz_opts_fini(opts); + return EXIT_FAILURE; + } + _zz_setratio(opts->minratio, opts->maxratio); _zz_setseed(opts->seed); @@ -396,8 +411,10 @@ 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->list) + setenv("ZZUF_LIST", opts->list, 1); + if(opts->ports) + setenv("ZZUF_PORTS", opts->ports, 1); if(opts->protect) setenv("ZZUF_PROTECT", opts->protect, 1); if(opts->refuse) @@ -450,8 +467,10 @@ 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->list) + _zz_list(opts->list); + if(opts->ports) + _zz_ports(opts->ports); if(opts->protect) _zz_protect(opts->protect); if(opts->refuse) @@ -1146,8 +1165,8 @@ static void usage(void) #if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM printf( "[-M megabytes] "); #endif - printf( "[-b ranges]\n"); - printf(" [-P protect] [-R refuse] [-p pick]"); + printf( "[-b ranges] [-p ports]\n"); + printf(" [-P protect] [-R refuse] [-l list]"); #if defined HAVE_REGEX_H printf( " [-I include] [-E exclude]"); #endif @@ -1176,12 +1195,13 @@ static void usage(void) #if defined HAVE_REGEX_H printf(" -I, --include only fuzz files matching \n"); #endif + printf(" -l, --list only fuzz Nth descriptor with N in \n"); printf(" -m, --md5 compute the output's MD5 hash\n"); #if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM printf(" -M, --max-memory maximum child virtual memory size in MB\n"); #endif printf(" -n, --network fuzz network input\n"); - printf(" -p, --pick only fuzz Nth descriptor with N in \n"); + printf(" -p, --ports only fuzz network destination ports in \n"); printf(" -P, --protect protect bytes and characters in \n"); printf(" -q, --quiet do not print children's messages\n"); printf(" -r, --ratio bit fuzzing ratio (default %g)\n", DEFAULT_RATIO);