* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
-#define FUZZING 1
+#define FUZZING_OVERRIDE_LLVMFuzzerTestOneInput
#include <zebra.h>
#include "lib/ringbuf.h"
-/* Main routine of bgpd. Treatment of argument and start bgp finite
- state machine is handled at here. */
-int main(int argc, char **argv)
-{
- int opt;
- int tmp_port;
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+static bool FuzzingInit(void) {
int bgp_port = BGP_PORT_DEFAULT;
struct list *addresses = list_new();
int no_fib_flag = 0;
int skip_runas = 0;
int instance = 0;
int buffer_size = BGP_SOCKET_SNDBUF_SIZE;
- char *address;
struct listnode *node;
addresses->cmp = (int (*)(void *, void *))strcmp;
- frr_preinit(&bgpd_di, argc, argv);
+ const char *name[] = { "bgpd" };
+
+ frr_preinit(&bgpd_di, 1, (char **) name);
-#ifdef FUZZING
/* Initialize basic BGP datastructures */
- bgp_master_init(frr_init_fast(), buffer_size);
+ bgp_master_init(frr_init_fast(), buffer_size, addresses);
bm->port = bgp_port;
bgp_option_set(BGP_OPT_NO_LISTEN);
- bm->address = bgp_address;
bgp_option_set(BGP_OPT_NO_FIB);
as_t as = 65001;
bgp_get(&b, &as, "default", BGP_INSTANCE_TYPE_DEFAULT);
+ return true;
+}
+
+static struct peer *FuzzingCreatePeer()
+{
union sockunion su;
sockunion_init(&su);
inet_pton(AF_INET, "10.1.1.1", &su.sin.sin_addr);
SET_FLAG(p->af_cap[afi][safi], 0x3FFF);
}
-#ifdef __AFL_HAVE_MANUAL_CONTROL
- __AFL_INIT();
-#endif
+ return p;
+}
+static struct peer *FuzzingPeer;
- uint8_t *input;
- int r = frrfuzz_read_input(&input);
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ static bool initialized;
- if (!input)
- return 0;
+ if (!initialized)
+ initialized = FuzzingInit();
+
+ /*
+ * In the AFL standalone case, the peer 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 peer must be destroyed before we return..
+ */
+ struct peer *p = (FuzzingPeer) ? FuzzingPeer : FuzzingCreatePeer();
- ringbuf_put(p->ibuf_work, input, r);
+
+ ringbuf_put(p->ibuf_work, data, size);
/*
* Simulate the read process done by bgp_process_reads().
* so we need to make sure that remains true for fuzzed input.
* */
if (!validate_header(p))
- exit(9);
+ return 0;
int result = 0;
- static unsigned char pktbuf[BGP_MAX_PACKET_SIZE];
+ unsigned char pktbuf[BGP_MAX_PACKET_SIZE];
uint16_t pktsize = 0;
ringbuf_peek(p->ibuf_work, BGP_MARKER_SIZE, &pktsize, sizeof(pktsize));
result = bgp_process_packet(&t);
}
- exit(result);
+ peer_delete(p);
+ FuzzingPeer = NULL;
+
+ return 0;
+};
+
+/* Fucking libFuzzer... */
+#ifndef FUZZING_LIBFUZZER
+/* Main routine of bgpd. Treatment of argument and start bgp finite
+ state machine is handled at here. */
+int main(int argc, char **argv)
+{
+ int opt;
+ int tmp_port;
+
+ int bgp_port = BGP_PORT_DEFAULT;
+ char *bgp_address = NULL;
+ int no_fib_flag = 0;
+ int no_zebra_flag = 0;
+ int skip_runas = 0;
+ int instance = 0;
+ int buffer_size = BGP_SOCKET_SNDBUF_SIZE;
+
+ frr_preinit(&bgpd_di, argc, argv);
+
+#ifdef FUZZING
+ FuzzingInit();
+ FuzzingPeer = FuzzingCreatePeer();
+
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+ __AFL_INIT();
#endif
+ uint8_t *input;
+ int r = frrfuzz_read_input(&input);
+ if (!input)
+ return 0;
+
+ return LLVMFuzzerTestOneInput(input, r);
+#endif
frr_opt_add(
"p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
/* Not reached. */
return 0;
}
+#endif /* FUZZING_LIBFUZZER */
SAN_FLAGS="$SAN_FLAGS -fsanitize=undefined"
])
fi
+if test "$enable_libfuzzer" = "yes"; then
+ AC_C_FLAG([-fsanitize=address,fuzzer], [
+ AC_MSG_ERROR([$CC does not support ASAN / libFuzzer.])
+ ], [
+ AC_MSG_NOTICE([WARNING - libFuzzer only enabled on supported daemons])
+ AC_MSG_NOTICE([WARNING - libFuzzer implies ASAN for all daemons])
+ SAN_FLAGS="$SAN_FLAGS -fsanitize=address"
+ BGPD_SAN_FLAGS="-fsanitize=fuzzer"
+ AC_DEFINE([FUZZING_LIBFUZZER], [1], [Compiling and linking with libFuzzer])
+ ])
+fi
AC_SUBST([SAN_FLAGS])
+AC_SUBST([BGPD_SAN_FLAGS])
dnl frr-format.so
if test "$with_frr_format" != "no" -a "$with_frr_format" != "yes" -a -n "$with_frr_format"; then
AS_HELP_STRING([--enable-memory-sanitizer], [enable MemorySanitizer support for detecting uninitialized memory reads]))
AC_ARG_ENABLE([undefined-sanitizer],
AS_HELP_STRING([--enable-undefined-sanitizer], [enable UndefinedBehaviorSanitizer support for detecting undefined behavior]))
+AC_ARG_ENABLE([libfuzzer],
+ AS_HELP_STRING([--libfuzzer], [enable libFuzzer]))
AC_ARG_WITH([crypto],
AS_HELP_STRING([--with-crypto=<internal|openssl>], [choose between different implementations of cryptographic functions(default value is --with-crypto=internal)]))
AC_ARG_WITH([frr-format],