From 411314ed4fbb407adc0cf50bfce5469f8d673e65 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 2 Nov 2017 10:56:03 -0400 Subject: [PATCH] configure, zebra: Add some debug code to allow for fuzzing 1) Write zserv api commands( one of each type ) to the side. This will allow us to use them as input for a fuzzer. 2) Add -c into zebra as a run-time option of we've turned on fuzzing. While in and of itself these are not terribly useful( you still need an external fuzzer ), they provide an infrastructure to allow tools like afl to test the zapi. Signed-off-by: Donald Sharp --- configure.ac | 6 ++++++ doc/install.texi | 4 ++++ zebra/main.c | 21 +++++++++++++++++++++ zebra/zserv.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ zebra/zserv.h | 4 ++++ 5 files changed, 82 insertions(+) diff --git a/configure.ac b/configure.ac index cae5061122..49bc652329 100755 --- a/configure.ac +++ b/configure.ac @@ -381,6 +381,8 @@ AC_ARG_ENABLE(cumulus, AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions])) AC_ARG_ENABLE(datacenter, AS_HELP_STRING([--enable-datacenter], [enable Compilation for Data Center Extensions])) +AC_ARG_ENABLE(fuzzing, + AS_HELP_STRING([--enable-fuzzing], [enable ability to fuzz various parts of FRR])) AC_ARG_ENABLE(rr-semantics, AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics])) AC_ARG_ENABLE([protobuf], @@ -432,6 +434,10 @@ else DFLT_NAME="traditional" fi +if test "${enable_fuzzing}" = "yes" ; then + AC_DEFINE(HANDLE_ZAPI_FUZZING,,Compile extensions to use with a fuzzer) +fi + if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) fi diff --git a/doc/install.texi b/doc/install.texi index 1930af95e6..19d9614420 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -101,6 +101,10 @@ needs libexecinfo, while on glibc support for this is part of libc itself. Turn on some options for compiling FRR within a development environment in mind. Specifically turn on -g3 -O0 for compiling options and add inclusion of grammar sandbox. +@item --enable-fuzzing +Turn on some compile options to allow you to run fuzzing tools +against the system. This tools is intended as a developer +only tool and should not be used for normal operations @end table You may specify any combination of the above options to the configure diff --git a/zebra/main.c b/zebra/main.c index cf677a7753..36c931c4ee 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -201,6 +201,9 @@ int main(int argc, char **argv) char *lblmgr_path = NULL; struct sockaddr_storage dummy; socklen_t dummylen; +#if defined(HANDLE_ZAPI_FUZZING) + char *fuzzing = NULL; +#endif frr_preinit(&zebra_di, argc, argv); @@ -208,6 +211,9 @@ int main(int argc, char **argv) "bakz:e:l:r" #ifdef HAVE_NETLINK "s:" +#endif +#if defined(HANDLE_ZAPI_FUZZING) + "c:" #endif , longopts, @@ -221,6 +227,9 @@ int main(int argc, char **argv) #ifdef HAVE_NETLINK " -s, --nl-bufsize Set netlink receive buffer size\n" #endif /* HAVE_NETLINK */ +#if defined(HANDLE_ZAPI_FUZZING) + " -c Bypass normal startup use this file for tetsting of zapi" +#endif ); while (1) { @@ -271,6 +280,11 @@ int main(int argc, char **argv) nl_rcvbufsize = atoi(optarg); break; #endif /* HAVE_NETLINK */ +#if defined(HANDLE_ZAPI_FUZZING) + case 'c': + fuzzing = optarg; + break; +#endif default: frr_help_exit(1); break; @@ -308,6 +322,13 @@ int main(int argc, char **argv) * routing socket. */ zebra_ns_init(); +#if defined(HANDLE_ZAPI_FUZZING) + if (fuzzing) { + zserv_read_file(fuzzing); + exit(0); + } +#endif + /* Process the configuration file. Among other configuration * directives we can meet those installing static routes. Such * requests will not be executed immediately, but queued in diff --git a/zebra/zserv.c b/zebra/zserv.c index cbd532339d..75ed4abe76 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2377,6 +2377,26 @@ static inline void zserv_handle_commands(struct zserv *client, } } +#if defined(HANDLE_ZAPI_FUZZING) +static void zserv_write_incoming(struct stream *orig, uint16_t command) +{ + char fname[MAXPATHLEN]; + struct stream *copy; + int fd = -1; + + copy = stream_dup(orig); + stream_set_getp(copy, 0); + + zserv_privs.change(ZPRIVS_RAISE); + snprintf(fname, MAXPATHLEN, "%s/%u", DAEMON_VTY_DIR, command); + fd = open(fname, O_CREAT | O_WRONLY | O_EXCL, 0644); + stream_flush(copy, fd); + close(fd); + zserv_privs.change(ZPRIVS_LOWER); + stream_free(copy); +} +#endif + /* Handler of zebra service request. */ static int zebra_client_read(struct thread *thread) { @@ -2387,7 +2407,11 @@ static int zebra_client_read(struct thread *thread) uint8_t marker, version; vrf_id_t vrf_id; struct zebra_vrf *zvrf; +#if defined(HANDLE_ZAPI_FUZZING) + int packets = 1; +#else int packets = zebrad.packets_to_process; +#endif /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD(thread); @@ -2477,6 +2501,9 @@ static int zebra_client_read(struct thread *thread) } } +#if defined(HANDLE_ZAPI_FUZZING) + zserv_write_incoming(client->ibuf, command); +#endif length -= ZEBRA_HEADER_SIZE; /* Debug packet information. */ @@ -3023,6 +3050,26 @@ static struct cmd_node forwarding_node = {FORWARDING_NODE, "", /* This node has no interface. */ 1}; +#if defined(HANDLE_ZAPI_FUZZING) +void zserv_read_file(char *input) +{ + int fd; + struct zserv *client = NULL; + struct thread t; + + zebra_client_create(-1); + client = zebrad.client_list->head->data; + t.arg = client; + + fd = open(input, O_RDONLY|O_NONBLOCK); + t.u.fd = fd; + + zebra_client_read(&t); + + close(fd); +} +#endif + /* Initialisation of zebra and installation of commands. */ void zebra_init(void) { diff --git a/zebra/zserv.h b/zebra/zserv.h index 279b56ec3c..60e055088a 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -193,4 +193,8 @@ extern int zebra_server_send_message(struct zserv *client); extern struct zserv *zebra_find_client(u_char proto); +#if defined(HANDLE_ZAPI_FUZZING) +extern void zserv_read_file(char *input); +#endif + #endif /* _ZEBRA_ZEBRA_H */ -- 2.39.5