On Thu, Jul 15, 2021 at 8:11 AM Evgeny Vereshchagin <evvers@xxxxx> wrote: > > It should make it easier to reproduce bugs found by OSS-Fuzz locally > without docker. The fuzz target can be built and run with the corpus > OSS-Fuzz has accumulated so far by running the following commands: > ``` > ./scripts/oss-fuzz.sh > wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip > unzip -d CORPUS public.zip > ./out/secilc-fuzzer CORPUS/ > ``` > > It was tested in https://github.com/google/oss-fuzz/pull/6026 > by pointing OSS-Fuzz to the branch containing the patch and > running all the tests with all the sanitizers and fuzzing engines > there: https://github.com/google/oss-fuzz/actions/runs/1024673143 > > [v2] > [1] oss-fuzz: make shellcheck happy > > [2] oss-fuzz: build libsepol only > > The fuzz target covers libsepol so it's unnecessary to build everything > else. Apart from that, the "LDFLAGS" kludge was removed since libsepol > is compatible with the sanitizers flags passed via CFLAGS only. It > should be brought back one way or another eventually though to fix > build failures like > ``` > clang -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L../src sefcontext_compile.o ../src/regex.o -lselinux -lpcre ../src/libselinux.a -lsepol -o sefcontext_compile > /usr/bin/ld: sefcontext_compile.o: in function `usage': > /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:271: undefined reference to `__asan_report_load8' > /usr/bin/ld: /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:292: undefined reference to `__asan_handle_no_return' > /usr/bin/ld: sefcontext_compile.o: in function `asan.module_ctor': > ``` > > [3] oss-fuzz: make it possible to run the script more than once > by removing various build artifacts > > [4] oss-fuzz: make it possible to run the script from any directory > > [5] oss-fuzz: be a little bit more specific about what the script does > > [6] oss-fuzz: stop overwriting all the Makefiles > > Signed-off-by: Evgeny Vereshchagin <evvers@xxxxx> Sorry for the delay. I have now been able to review and test your script and it seems to work perfectly. Thanks! Acked-by: Nicolas Iooss <nicolas.iooss@xxxxxxx> Thanks, Nicolas > --- > libsepol/fuzz/secilc-fuzzer.c | 69 +++++++++++++++++++++++++++++++++++ > scripts/oss-fuzz.sh | 59 ++++++++++++++++++++++++++++++ > 2 files changed, 128 insertions(+) > create mode 100644 libsepol/fuzz/secilc-fuzzer.c > create mode 100755 scripts/oss-fuzz.sh > > diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c > new file mode 100644 > index 00000000..255b3241 > --- /dev/null > +++ b/libsepol/fuzz/secilc-fuzzer.c > @@ -0,0 +1,69 @@ > +#include <stdlib.h> > +#include <stdio.h> > +#include <stdint.h> > +#include <string.h> > +#include <getopt.h> > +#include <sys/stat.h> > + > +#include <sepol/cil/cil.h> > +#include <sepol/policydb.h> > + > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { > + enum cil_log_level log_level = CIL_ERR; > + struct sepol_policy_file *pf = NULL; > + FILE *dev_null = NULL; > + int target = SEPOL_TARGET_SELINUX; > + int disable_dontaudit = 0; > + int multiple_decls = 0; > + int disable_neverallow = 0; > + int preserve_tunables = 0; > + int policyvers = POLICYDB_VERSION_MAX; > + int mls = -1; > + int attrs_expand_generated = 0; > + struct cil_db *db = NULL; > + sepol_policydb_t *pdb = NULL; > + > + cil_set_log_level(log_level); > + > + cil_db_init(&db); > + cil_set_disable_dontaudit(db, disable_dontaudit); > + cil_set_multiple_decls(db, multiple_decls); > + cil_set_disable_neverallow(db, disable_neverallow); > + cil_set_preserve_tunables(db, preserve_tunables); > + cil_set_mls(db, mls); > + cil_set_target_platform(db, target); > + cil_set_policy_version(db, policyvers); > + cil_set_attrs_expand_generated(db, attrs_expand_generated); > + > + if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK) > + goto exit; > + > + if (cil_compile(db) != SEPOL_OK) > + goto exit; > + > + if (cil_build_policydb(db, &pdb) != SEPOL_OK) > + goto exit; > + > + if (sepol_policydb_optimize(pdb) != SEPOL_OK) > + goto exit; > + > + dev_null = fopen("/dev/null", "w"); > + if (dev_null == NULL) > + goto exit; > + > + if (sepol_policy_file_create(&pf) != 0) > + goto exit; > + > + sepol_policy_file_set_fp(pf, dev_null); > + > + if (sepol_policydb_write(pdb, pf) != 0) > + goto exit; > +exit: > + if (dev_null != NULL) > + fclose(dev_null); > + > + cil_db_destroy(&db); > + sepol_policydb_free(pdb); > + sepol_policy_file_free(pf); > + return 0; > +} > diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh > new file mode 100755 > index 00000000..16cc3c0a > --- /dev/null > +++ b/scripts/oss-fuzz.sh > @@ -0,0 +1,59 @@ > +#!/bin/bash > + > +# The script is used to build the fuzz targets run on ClusterFuzz. It has to be > +# compatible with the "build.sh" script described at > +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh > +# More precisely, it should use environment variables like OUT, LIB_FUZZING_ENGINE > +# and so on (https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment), > +# and the fuzz targets have to be linked with $CXX even though the project is written > +# in C: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements > + > +# To make it easier to build the fuzz targets locally, the script can also work in "local" > +# mode. To run secilc-fuzzer against a test case (named, say, CRASH) triggering an issue > +# the following commands should be run > +# > +# $ ./scripts/oss-fuzz.sh > +# $ ./out/secilc-fuzzer CRASH > + > +# To run the fuzzer against the corpus OSS-Fuzz has accumulated so far it should be > +# downloaded, unpacked and passed to the fuzzer: > +# > +# $ wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip > +# $ unzip -d CORPUS public.zip > +# $ ./out/secilc-fuzzer CORPUS/ > + > +set -eux > + > +cd "$(dirname -- "$0")/.." > + > +export DESTDIR=${DESTDIR:-$(pwd)/DESTDIR} > + > +SANITIZER=${SANITIZER:-address} > +flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link" > + > +export CC=${CC:-clang} > +export CFLAGS=${CFLAGS:-$flags} > + > +export CXX=${CXX:-clang++} > +export CXXFLAGS=${CXXFLAGS:-$flags} > + > +export OUT=${OUT:-$(pwd)/out} > +mkdir -p "$OUT" > + > +export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer} > + > +rm -rf "$DESTDIR" > +make -C libsepol clean > +# LIBSO and LIBMAP shouldn't be expanded here because their values are unknown until Makefile > +# has been read by make > +# shellcheck disable=SC2016 > +make -C libsepol V=1 LD_SONAME_FLAGS='-soname,$(LIBSO),--version-script=$(LIBMAP)' -j"$(nproc)" install > + > +# CFLAGS, CXXFLAGS and LIB_FUZZING_ENGINE have to be split to be accepted by > +# the compiler/linker so they shouldn't be quoted > +# shellcheck disable=SC2086 > +$CC $CFLAGS -I"$DESTDIR/usr/include" -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c > +# shellcheck disable=SC2086 > +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o "$DESTDIR/usr/lib/libsepol.a" -o "$OUT/secilc-fuzzer" > + > +zip -r "$OUT/secilc-fuzzer_seed_corpus.zip" secilc/test > -- > 2.31.1 >