From: 0x34d Date: Sun, 9 Oct 2022 11:37:02 +0000 (+0530) Subject: oss-fuzz and fuzzer files #551 X-Git-Tag: 1.0.16~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=14d35a0854059d5b9a2c88ae8df350cbcc24e886;p=thirdparty%2Flldpd.git oss-fuzz and fuzzer files #551 Signed-off-by: 0x34d --- diff --git a/README.md b/README.md index c57353ac..18fe2b87 100644 --- a/README.md +++ b/README.md @@ -368,6 +368,17 @@ To enable code coverage, use: --directory src --capture --output-file gcov.info genhtml gcov.info --output-directory coverage +## Fuzzing +libfuzzer: + +``` +export CC=clang +export CXX=clang++ + +sh ./tests/build.sh ASan +sh ./tests/build.sh Run +``` + ## Embedding To embed lldpd into an existing system, there are two point of entries: diff --git a/configure.ac b/configure.ac index 11ec21a8..9a028047 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,21 @@ elif test x"$hardening" != x"no"; then fi ]) +#Fuzzer +AC_ARG_ENABLE([fuzzer], + AS_HELP_STRING([--enable-fuzzer], + [Enable fuzzing @<:@default=no@:>@]), + [ +case "$enableval" in + no) fuzzer= ;; + yes) fuzzer="-fsanitize=fuzzer" ;; + *) fuzzer="$enableval" ;; +esac +if test x"$fuzzer" != x; then + AC_SUBST([FUZZENGINE], ["$fuzzer"]) +fi + ]) + # Code coverage AC_ARG_ENABLE([gcov], AS_HELP_STRING([--enable-gcov], @@ -404,6 +419,7 @@ AC_SUBST([LLDP_CFLAGS]) AC_SUBST([LLDP_CPPFLAGS]) AC_SUBST([LLDP_LDFLAGS]) AC_SUBST([LLDP_BIN_LDFLAGS]) +AM_CONDITIONAL([BUILD_FUZZER], [test x"$fuzzer" != x]) AM_CONDITIONAL([HAVE_CHECK], [test x"$have_check" = x"yes"]) AM_CONDITIONAL([USE_SNMP], [test x"$with_snmp" = x"yes"]) AM_CONDITIONAL([USE_XML], [test x"$with_xml" = x"yes"]) diff --git a/tests/Makefile.am b/tests/Makefile.am index 34c99fd0..49951dc2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,4 +63,11 @@ check_PROGRAMS += $(TESTS) endif +if BUILD_FUZZER +noinst_PROGRAMS = fuzz-decode +fuzz-decode_CFLAGS=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fPIE +fuzz-decode_SOURCES = decode.c +fuzz-decode_LDADD = $(LDADD) $(FUZZENGINE) +endif + MOSTLYCLEANFILES = *.pcap diff --git a/tests/build-fuzzer.sh b/tests/build-fuzzer.sh new file mode 100644 index 00000000..aa287575 --- /dev/null +++ b/tests/build-fuzzer.sh @@ -0,0 +1,30 @@ +#!/bin/bash -eu + +build(){ + export CFLAGS="$1" + export CXXFLAGS="$1" + + ./autogen.sh + ./configure CC="$CC" CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" \ + --enable-fuzzer=yes --disable-shared --disable-hardening --enable-pie + + make -j$(nproc) + mkdir -p tests/seed/fuzz-decode_Corpus +} + +run(){ + cd tests + ./fuzz-decode seed/fuzz-decode_Corpus seed/fuzz-decode_seed_corpus +} + +help(){ + echo "use: ./$0 ASan | UBSan | MSan | Run" +} + +case $1 in + ASan) build "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link" ;; + UBSan) build "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr -fsanitize=fuzzer-no-link" ;; + MSan) build "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize-memory-track-origins -fsanitize=fuzzer-no-link" ;; + run) run $2 ;; + *) help ;; +esac diff --git a/tests/decode.c b/tests/decode.c index 9f75cc65..6ab0829f 100644 --- a/tests/decode.c +++ b/tests/decode.c @@ -58,6 +58,69 @@ tohex(char *str, size_t len) exit(5); \ } +int decode(char *frame, int size, + struct lldpd_hardware *hardware, struct lldpd_chassis **nchassis, struct lldpd_port **nport) { + /* For decoding, we only need a very basic hardware */ + memset(hardware, 0, sizeof(struct lldpd_hardware)); + hardware->h_mtu = 1500; + strlcpy(hardware->h_ifname, "test", sizeof(hardware->h_ifname)); + + int decoded = 0; + if (lldp_decode(NULL, frame, size, hardware, nchassis, nport) == -1) { + fprintf(stderr, "Not decoded as a LLDP frame\n"); + } else { + fprintf(stderr, "Decoded as a LLDP frame\n"); + decoded = 1; + } +#if defined ENABLE_CDP || defined ENABLE_FDP + if (cdp_decode(NULL, frame, size, hardware, nchassis, nport) == -1) { + fprintf(stderr, "Not decoded as a CDP frame\n"); + } else { + fprintf(stderr, "Decoded as a CDP frame\n"); + decoded = 1; + } +#endif +#ifdef ENABLE_SONMP + if (sonmp_decode(NULL, frame, size, hardware, nchassis, nport) == -1) { + fprintf(stderr, "Not decoded as a SONMP frame\n"); + } else { + fprintf(stderr, "Decoded as a SONMP frame\n"); + decoded = 1; + } +#endif +#ifdef ENABLE_EDP + if (edp_decode(NULL, frame, size, hardware, nchassis, nport) == -1) { + fprintf(stderr, "Not decoded as a EDP frame\n"); + } else { + fprintf(stderr, "Decoded as a EDP frame\n"); + decoded = 1; + } +#endif + return decoded; +} + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + +#define kMinInputLength 30 +#define kMaxInputLength 1500 + +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size < kMinInputLength || size > kMaxInputLength){ + return 0; + } + struct lldpd_hardware hardware; + struct lldpd_chassis *nchassis = NULL; + struct lldpd_port *nport = NULL; + if (!decode((char*)data, (int)size, &hardware, &nchassis, &nport)) { + return -1; + } + lldpd_port_cleanup(nport, 1); free(nport); + lldpd_chassis_cleanup(nchassis, 1); + return 0; +} + +#else + int main(int argc, char **argv) { @@ -87,47 +150,11 @@ main(int argc, char **argv) memcpy(&rechdr, buf + sizeof(hdr), sizeof(rechdr)); assert(len >= sizeof(hdr) + sizeof(rechdr) + rechdr.incl_len); - /* For decoding, we only need a very basic hardware */ struct lldpd_hardware hardware; - memset(&hardware, 0, sizeof(struct lldpd_hardware)); - hardware.h_mtu = 1500; - strlcpy(hardware.h_ifname, "test", sizeof(hardware.h_ifname)); - - char *frame = buf + sizeof(hdr) + sizeof(rechdr); struct lldpd_chassis *nchassis = NULL; struct lldpd_port *nport = NULL; - int decoded = 0; - if (lldp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) { - fprintf(stderr, "Not decoded as a LLDP frame\n"); - } else { - fprintf(stderr, "Decoded as a LLDP frame\n"); - decoded = 1; - } -#if defined ENABLE_CDP || defined ENABLE_FDP - if (cdp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) { - fprintf(stderr, "Not decoded as a CDP frame\n"); - } else { - fprintf(stderr, "Decoded as a CDP frame\n"); - decoded = 1; - } -#endif -#ifdef ENABLE_SONMP - if (sonmp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) { - fprintf(stderr, "Not decoded as a SONMP frame\n"); - } else { - fprintf(stderr, "Decoded as a SONMP frame\n"); - decoded = 1; - } -#endif -#ifdef ENABLE_EDP - if (edp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) { - fprintf(stderr, "Not decoded as a EDP frame\n"); - } else { - fprintf(stderr, "Decoded as a EDP frame\n"); - decoded = 1; - } -#endif - if (!decoded) exit(1); + if (!decode(buf + sizeof(hdr) + sizeof(rechdr), rechdr.incl_len, &hardware, &nchassis, &nport)) + exit(1); printf("Chassis:\n"); printf(" Index: %" PRIu16 "\n", nchassis->c_index); @@ -245,3 +272,5 @@ main(int argc, char **argv) #endif exit(0); } + +#endif diff --git a/tests/seed/fuzz-decode_seed_corpus/cdp.0.raw b/tests/seed/fuzz-decode_seed_corpus/cdp.0.raw new file mode 100644 index 00000000..b5dad7c6 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/cdp.0.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/cdp.1.raw b/tests/seed/fuzz-decode_seed_corpus/cdp.1.raw new file mode 100644 index 00000000..68fca42c Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/cdp.1.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/cdp.2.raw b/tests/seed/fuzz-decode_seed_corpus/cdp.2.raw new file mode 100644 index 00000000..691ca4aa Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/cdp.2.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/cdp.3.raw b/tests/seed/fuzz-decode_seed_corpus/cdp.3.raw new file mode 100644 index 00000000..2af7e8ca Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/cdp.3.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/edp.0.raw b/tests/seed/fuzz-decode_seed_corpus/edp.0.raw new file mode 100644 index 00000000..42a6dbc5 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/edp.0.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/edp.1.raw b/tests/seed/fuzz-decode_seed_corpus/edp.1.raw new file mode 100644 index 00000000..5febdc59 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/edp.1.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/edp.2.raw b/tests/seed/fuzz-decode_seed_corpus/edp.2.raw new file mode 100644 index 00000000..05fbb8d0 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/edp.2.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/edp.3.raw b/tests/seed/fuzz-decode_seed_corpus/edp.3.raw new file mode 100644 index 00000000..7b0ca07d Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/edp.3.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/edp.4.raw b/tests/seed/fuzz-decode_seed_corpus/edp.4.raw new file mode 100644 index 00000000..e8dfefb3 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/edp.4.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/lldp.0.raw b/tests/seed/fuzz-decode_seed_corpus/lldp.0.raw new file mode 100644 index 00000000..21002a7e Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/lldp.0.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/lldp.1.raw b/tests/seed/fuzz-decode_seed_corpus/lldp.1.raw new file mode 100644 index 00000000..279e2393 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/lldp.1.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/sonmp.0.raw b/tests/seed/fuzz-decode_seed_corpus/sonmp.0.raw new file mode 100644 index 00000000..438c7714 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/sonmp.0.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/sonmp.1.raw b/tests/seed/fuzz-decode_seed_corpus/sonmp.1.raw new file mode 100644 index 00000000..79901072 Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/sonmp.1.raw differ diff --git a/tests/seed/fuzz-decode_seed_corpus/sonmp.2.raw b/tests/seed/fuzz-decode_seed_corpus/sonmp.2.raw new file mode 100644 index 00000000..7681634b Binary files /dev/null and b/tests/seed/fuzz-decode_seed_corpus/sonmp.2.raw differ