]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: add libFuzzer support
authorQuentin Young <qlyoung@cumulusnetworks.com>
Mon, 13 Jan 2020 20:32:08 +0000 (15:32 -0500)
committerQuentin Young <qlyoung@nvidia.com>
Mon, 15 Nov 2021 19:52:42 +0000 (14:52 -0500)
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
configure.ac
zebra/main.c
zebra/subdir.am

index 669d0b53874100b10b343b87925482f44e65bee9..3517f5307e37893fe5f3dbc6a9af31c38837163c 100644 (file)
@@ -404,11 +404,13 @@ if test "$enable_libfuzzer" = "yes"; then
     AC_MSG_NOTICE([WARNING - libFuzzer only enabled on supported daemons])
     SAN_FLAGS="$SAN_FLAGS -fsanitize=fuzzer-no-link"
     BGPD_SAN_FLAGS="-fsanitize=fuzzer"
+    ZEBRA_SAN_FLAGS="-fsanitize=fuzzer"
     AC_DEFINE([FUZZING_LIBFUZZER], [1], [Compiling and linking with libFuzzer])
   ])
 fi
 AC_SUBST([SAN_FLAGS])
 AC_SUBST([BGPD_SAN_FLAGS])
+AC_SUBST([ZEBRA_SAN_FLAGS])
 
 dnl frr-format.so
 if test "$with_frr_format" != "no" -a "$with_frr_format" != "yes" -a -n "$with_frr_format"; then
index 9d87f12a1eff41344543fd97f8032736a7b734d0..ce1c27912a015384bc332ec911a5d6125049ddb4 100644 (file)
@@ -279,37 +279,29 @@ FRR_DAEMON_INFO(
        .n_yang_modules = array_size(zebra_yang_modules),
 );
 
-/* Main startup routine. */
-int main(int argc, char **argv)
-{
-       // int batch_mode = 0;
-       char *zserv_path = NULL;
-       char *vrf_default_name_configured = NULL;
-       struct sockaddr_storage dummy;
-       socklen_t dummylen;
-       bool asic_offload = false;
-       bool notify_on_ack = true;
+#ifdef FUZZING
 
-#if defined(HANDLE_NETLINK_FUZZING)
-       char *netlink_fuzzing = NULL;
-#endif /* HANDLE_NETLINK_FUZZING */
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
+static bool FuzzingInit(void)
+{
        graceful_restart = 0;
        vrf_configure_backend(VRF_BACKEND_VRF_LITE);
 
-       frr_preinit(&zebra_di, argc, argv);
+       const char *name[] = { "zebra" };
 
-#ifdef FUZZING
-       zrouter.master = frr_init_fast();
+       frr_preinit(&zebra_di, 1, (char **) name);
 
        /* Zebra related initialize. */
+       zrouter.master = frr_init_fast();
+
        zebra_router_init();
        zserv_init();
        rib_init();
        zebra_if_init();
        zebra_debug_init();
        router_id_cmd_init();
-       zebra_ns_init((const char *)vrf_default_name_configured);
+       zebra_ns_init((const char *)NULL);
        zebra_vty_init();
        access_list_init();
        prefix_list_init();
@@ -324,7 +316,73 @@ int main(int argc, char **argv)
        zebra_error_init();
        frr_pthread_init();
 
-       struct zserv *zc = zserv_client_create(69);
+       return true;
+}
+
+#ifndef FUZZING_LIBFUZZER
+static struct zserv *FuzzingZc;
+#endif /* FUZZING_LIBFUZZER */
+
+static bool FuzzingInitialized;
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+       if (!FuzzingInitialized) {
+               FuzzingInit();
+               FuzzingInitialized = true;
+       }
+
+       /*
+        * In the AFL standalone case, the client will already be created for
+        * us before __AFL_INIT() is called to speed things up. We can't pass
+        * it as an argument because the function signature must match
+        * libFuzzer's expectations.
+        *
+        * In the libFuzzer case, we need to create it each time.
+        *
+        * In both cases the client must be destroyed before we return..
+        */
+       struct zserv *zc;
+#ifdef FUZZING_LIBFUZZER
+       zc = zserv_client_create(69);
+#else
+       zc = FuzzingZc;
+#endif /* FUZZING_LIBFUZZER */
+
+       struct stream *s = stream_new(size + 1);
+       stream_put(s, data, size);
+
+       zserv_handle_commands(zc, s);
+
+       stream_free(s);
+
+done:
+       zserv_close_client(zc);
+
+       return 0;
+}
+#endif /* FUZZING */
+
+#ifndef FUZZING_LIBFUZZER
+
+CPP_NOTICE("Not using LibFuzzer, compiling in main symbol!")
+
+/* Main startup routine. */
+int main(int argc, char **argv)
+{
+       // int batch_mode = 0;
+       char *zserv_path = NULL;
+       char *vrf_default_name_configured = NULL;
+       struct sockaddr_storage dummy;
+       socklen_t dummylen;
+#if defined(HANDLE_NETLINK_FUZZING)
+       char *netlink_fuzzing = NULL;
+#endif /* HANDLE_NETLINK_FUZZING */
+
+#ifdef FUZZING
+       FuzzingInit();
+       FuzzingInitialized = true;
+       FuzzingZc = zserv_client_create(69);
 
 #ifdef __AFL_HAVE_MANUAL_CONTROL
        __AFL_INIT();
@@ -333,19 +391,20 @@ int main(int argc, char **argv)
        uint8_t *input;
        int r = frrfuzz_read_input(&input);
 
-       struct stream *s = stream_new(r + 1);
-       stream_put(s, input, r);
-
-       zserv_handle_commands(zc, s);
+       int ret = LLVMFuzzerTestOneInput(input, r);
 
-       stream_free(s);
        if (r > 0 && input) {
                free(input);
        }
 
-       return 0;
+       return ret;
 #endif /* FUZZING */
 
+       graceful_restart = 0;
+       vrf_configure_backend(VRF_BACKEND_VRF_LITE);
+
+       frr_preinit(&zebra_di, argc, argv);
+
        frr_opt_add(
                "baz:e:o:rK:"
 #ifdef HAVE_NETLINK
@@ -550,3 +609,4 @@ int main(int argc, char **argv)
        /* Not reached... */
        return 0;
 }
+#endif /* FUZZING_LIBFUZZER */
index f0cc6ce71b22df031ac9f8e6a53e2f8fa93c6406..245ab32b091fd92a7ad45f5456c38ca1388960ff 100644 (file)
@@ -50,6 +50,7 @@ man8 += $(MANBUILD)/frr-zebra.8
 ## endif ZEBRA
 endif
 
+zebra_zebra_LDFLAGS = $(AM_LDFLAGS) $(ZEBRA_SAN_FLAGS)
 zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP)
 if HAVE_PROTOBUF3
 zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)