From 14d35a0854059d5b9a2c88ae8df350cbcc24e886 Mon Sep 17 00:00:00 2001 From: 0x34d Date: Sun, 9 Oct 2022 17:07:02 +0530 Subject: [PATCH] oss-fuzz and fuzzer files #551 Signed-off-by: 0x34d --- README.md | 11 ++ configure.ac | 16 +++ tests/Makefile.am | 7 ++ tests/build-fuzzer.sh | 30 +++++ tests/decode.c | 105 +++++++++++------- tests/seed/fuzz-decode_seed_corpus/cdp.0.raw | Bin 0 -> 120 bytes tests/seed/fuzz-decode_seed_corpus/cdp.1.raw | Bin 0 -> 134 bytes tests/seed/fuzz-decode_seed_corpus/cdp.2.raw | Bin 0 -> 300 bytes tests/seed/fuzz-decode_seed_corpus/cdp.3.raw | Bin 0 -> 318 bytes tests/seed/fuzz-decode_seed_corpus/edp.0.raw | Bin 0 -> 96 bytes tests/seed/fuzz-decode_seed_corpus/edp.1.raw | Bin 0 -> 96 bytes tests/seed/fuzz-decode_seed_corpus/edp.2.raw | Bin 0 -> 124 bytes tests/seed/fuzz-decode_seed_corpus/edp.3.raw | Bin 0 -> 338 bytes tests/seed/fuzz-decode_seed_corpus/edp.4.raw | Bin 0 -> 342 bytes tests/seed/fuzz-decode_seed_corpus/lldp.0.raw | Bin 0 -> 60 bytes tests/seed/fuzz-decode_seed_corpus/lldp.1.raw | Bin 0 -> 323 bytes .../seed/fuzz-decode_seed_corpus/sonmp.0.raw | Bin 0 -> 33 bytes .../seed/fuzz-decode_seed_corpus/sonmp.1.raw | Bin 0 -> 33 bytes .../seed/fuzz-decode_seed_corpus/sonmp.2.raw | Bin 0 -> 60 bytes 19 files changed, 131 insertions(+), 38 deletions(-) create mode 100644 tests/build-fuzzer.sh create mode 100644 tests/seed/fuzz-decode_seed_corpus/cdp.0.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/cdp.1.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/cdp.2.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/cdp.3.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/edp.0.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/edp.1.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/edp.2.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/edp.3.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/edp.4.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/lldp.0.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/lldp.1.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/sonmp.0.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/sonmp.1.raw create mode 100644 tests/seed/fuzz-decode_seed_corpus/sonmp.2.raw 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 0000000000000000000000000000000000000000..b5dad7c645356a299d2f567164c7ba5d132d8d27 GIT binary patch literal 120 zc-muR;5l>VOq@X9^Om&?S*untGcfQdFfeYh`p&?}An2A^R9vEvoRL^uoLS7k#30DP zz`)4Jc!q&xjbNWD12cn&TVipEYe`0GQC@0^f}y@C0}BHOP>~=5D}%T*M4v)RYH@N= TW=1 literal 0 Hc-jL100001 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 0000000000000000000000000000000000000000..68fca42c2fb84ab887dcb45388ff27f124a1c03b GIT binary patch literal 134 zc-muR;5l>VOq@X9^Om&?6{}V;GcfQdFfeU7k2*GwMeK!7jDb9Odu(l214Vmgb0OdBq@r^IGr{@^TT9H$&I9I58wf^ zEx6Mocm${I!sYwRL!jTbE&L4k`)e}X?K%K`1oH9y3j}%*g)?&rHkpaYkI zOt~nyw4nrn(SBx5(UsjFC)~Q6D zsZVd>TGaC<_|hOda-9HbQvtG(s^?Yq#+SI*aI_ukE)kY$+wP6y95&0ErHV&F53Wvo Hg+>1W>DyG3 literal 0 Hc-jL100001 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 0000000000000000000000000000000000000000..2af7e8ca05581317bf30ea60cba27649d5cd4df7 GIT binary patch literal 318 zc-lo!!A^rf6nvCwOl@Ksf8gDOq|}AzqTY}|(nNy+QoT~T1)>GAtRehT$B^c`P;0vBAYGb&gkhzTd~>lRH~;j$ErmrS%3 zf5)I^JP}2iVbnE(?J%mgqD?r%$ufvg6FVJki;#a@bBEn{F`o4~t{88MszlRTSlSJh zNa#IzPUK+}`0=X~dZ=wvQ=hn1-SHyJ1!}2|=KUQt9T05vi*Kmj`&OY(mpU_b&h85mdqBA^$4 literal 0 Hc-jL100001 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 0000000000000000000000000000000000000000..05fbb8d08b00e6db9e7440c9ed279fa357a36748 GIT binary patch literal 124 zc-mulpv}O*5GT<0yk#vz-l|p13_yY1j0_BE8b=tIVKOsW8Ki;A<}yHmTV_#li9(o< mqaOoMN``@fHz?Cvm2KH literal 0 Hc-jL100001 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 0000000000000000000000000000000000000000..7b0ca07db4948cc4ddf6984f3b2440ad4a190282 GIT binary patch literal 338 zc-mulpv?dTEYnzB@)=!Ltzu>X3hZWNV6af;2aFE`GlAg+0RMPQc>n+a literal 0 Hc-jL100001 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 0000000000000000000000000000000000000000..e8dfefb3b32b3a85a9b89b2a81fcad06abed1370 GIT binary patch literal 342 zc-mulpv?dTEYnzB@)X3hZWNV00*EVHSYN%w%OqX<%SrWPk#f)U?FXoDv4- z#Js%x5{2T#vQ&knqRf=^RD~3XltM|qLSC7IhH8o?7XyP|K1@0-zeu6Dv>>&}3C#D* zD=tw`O#zt+vV#E$_$DTY2qXsv-^iqN3iZUGO;eTIX<~aPSe38!SmsP PM`BIN79-*mFirs9YvxWy literal 0 Hc-jL100001 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 0000000000000000000000000000000000000000..438c7714287112f65def000ea8016ca55ab5be57 GIT binary patch literal 33 oc-muRXk=hyh!g00-m;cKc-1Oq28Kq)MQa56R2djp7