diff --git a/projects/sudoers/Dockerfile b/projects/sudoers/Dockerfile index 916ce7bfa..96977ba22 100755 --- a/projects/sudoers/Dockerfile +++ b/projects/sudoers/Dockerfile @@ -19,4 +19,3 @@ RUN git clone https://github.com/sudo-project/sudo WORKDIR $SRC/sudo COPY build.sh $SRC/ -COPY fuzz_* $SRC/ diff --git a/projects/sudoers/build.sh b/projects/sudoers/build.sh index 2be316858..635739454 100755 --- a/projects/sudoers/build.sh +++ b/projects/sudoers/build.sh @@ -15,25 +15,70 @@ # ################################################################################ -if [ $SANITIZER == "address" ]; then - export LDFLAGS="-fsanitize=address" -elif [ $SANITIZER == "undefined" ]; then - export LDFLAGS="-fsanitize=undefined" -elif [ $SANITIZER == "coverage" ]; then - export LDFLAGS="$CFLAGS" +# Debugging +env + +# Move ASAN-specific flags into ASAN_CFLAGS and ASAN_LDFLAGS +# That way they don't affect configure but will get used when building. +if [ $SANITIZER == "coverage" ]; then + export ASAN_CFLAGS="$COVERAGE_FLAGS" + export ASAN_LDFLAGS="$COVERAGE_FLAGS" + CFLAGS="`echo \"$CFLAGS\" | sed \"s/ $COVERAGE_FLAGS//\"`" +else + export ASAN_CFLAGS="$SANITIZER_FLAGS" + export ASAN_LDFLAGS="$SANITIZER_FLAGS" + CFLAGS="`echo \"$CFLAGS\" | sed \"s/ $SANITIZER_FLAGS//\"`" fi -./configure --enable-static-sudoers --enable-static --disable-shared-libutil -make +# Build sudo with static libs for simpler fuzzing +./configure --enable-static-sudoers --enable-static --disable-shared-libutil \ + --disable-leaks --enable-warnings --enable-werror +make -j$(nproc) -# Fuzz json parser -cd lib/iolog/ -$CC $CFLAGS -c -I../../include -I../.. -I. $SRC/fuzz_iolog_json_parse.c -fPIC -DPIC -o .libs/tmp_fuzz -$CXX $CXXFLAGS $LIB_FUZZING_ENGINE .libs/tmp_fuzz -o $OUT/fuzz_iolog_json_parse \ - .libs/libsudo_iolog.a ../eventlog/.libs/libsudo_eventlog.a ../util/.libs/libsudo_util.a +# Fuzz I/O log JSON parser +cd lib/iolog +$CC $CFLAGS $ASAN_CFLAGS -c -I../../include -I../.. -I. \ + regress/fuzz/fuzz_iolog_json.c +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzz_iolog_json \ + fuzz_iolog_json.o .libs/libsudo_iolog.a \ + ../eventlog/.libs/libsudo_eventlog.a ../util/.libs/libsudo_util.a -# Fuzz libsudoers parsing +# Corpus for fuzzing I/O log JSON parser +mkdir $WORK/corpus +for f in `find regress/iolog_json -name '*.in'`; do + cp $f $WORK/corpus/`sha1sum $f | cut -d' ' -f1` +done +zip -j $OUT/fuzz_iolog_json_seed_corpus.zip $WORK/corpus/* +rm -rf $WORK/corpus + +# Fuzz sudoers parser cd ../../plugins/sudoers -$CC $CFLAGS -c -I../../include -I../.. -I. $SRC/fuzz_sudoers_parse.c -fPIC -DPIC -o fuzz_sudoers_parse.o -$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_sudoers_parse.o -o $OUT/fuzz_sudoers_parse \ - ./.libs/libparsesudoers.a ./.libs/sudoers.a net_ifs.o parse_ldif.o ldap_util.o -lcrypt +$CC $CFLAGS $ASAN_CFLAGS -c -I../../include -I../.. -I. \ + regress/fuzz/fuzz_sudoers.c +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzz_sudoers \ + fuzz_sudoers.o locale.o stubs.o sudo_printf.o \ + .libs/libparsesudoers.a ../../lib/util/.libs/libsudo_util.a + +# Corpus for fuzzing sudoers parser +mkdir $WORK/corpus +for f in sudoers `find regress/sudoers -name '*.in'`; do + cp $f $WORK/corpus/`sha1sum $f | cut -d' ' -f1` +done +zip -j $OUT/fuzz_sudoers_seed_corpus.zip $WORK/corpus/* +rm -rf $WORK/corpus + +# Fuzz sudoers LDIF parser (used by cvtsudoers) +cd ../../plugins/sudoers +$CC $CFLAGS $ASAN_CFLAGS -c -I../../include -I../.. -I. \ + regress/fuzz/fuzz_sudoers_ldif.c +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzz_sudoers_ldif \ + fuzz_sudoers_ldif.o parse_ldif.o ldap_util.o fmtsudoers.o locale.o stubs.o \ + sudo_printf.o .libs/libparsesudoers.a ../../lib/util/.libs/libsudo_util.a + +# Corpus for fuzzing sudoers LDIF parser +mkdir $WORK/corpus +for f in `find regress/sudoers -name '*.ldif.ok' \! -size 0`; do + cp $f $WORK/corpus/`sha1sum $f | cut -d' ' -f1` +done +zip -j $OUT/fuzz_sudoers_ldif_seed_corpus.zip $WORK/corpus/* +rm -rf $WORK/corpus diff --git a/projects/sudoers/fuzz_iolog_json_parse.c b/projects/sudoers/fuzz_iolog_json_parse.c deleted file mode 100644 index 4ffb2279b..000000000 --- a/projects/sudoers/fuzz_iolog_json_parse.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright 2021 Google LLC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include -#include -#include - -#include - -#include -#include -#ifdef HAVE_STDBOOL_H -# include -#else -# include "compat/stdbool.h" -#endif /* HAVE_STDBOOL_H */ -#include -#include -#include -#include -#include -#include - -#include "sudo_compat.h" -#include "sudo_debug.h" -#include "sudo_eventlog.h" -#include "sudo_fatal.h" -#include "sudo_gettext.h" -#include "sudo_iolog.h" -#include "sudo_util.h" - -#include "iolog_json.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - char filename[256]; - sprintf(filename, "/tmp/fuzz-iolog.XXXXXX", getpid()); - - int fp = mkstemp(filename); - if (fp < 0) { - return 0; - } - write(fp, data, size); - close(fp); - - FILE *fd = fopen(filename,"rb"); - if (fd == -1) { - return 0; - } - - struct json_object root; - if (iolog_parse_json(fd, filename, &root)) { - free_json_items(&root.items); - } - fclose(fd); - - remove(filename); - return 0; -} diff --git a/projects/sudoers/fuzz_sudoers_parse.c b/projects/sudoers/fuzz_sudoers_parse.c deleted file mode 100644 index 703e7a813..000000000 --- a/projects/sudoers/fuzz_sudoers_parse.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2021 Google LLC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include -#include - -#include -#include -#include -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#include -#include -#include -#include -#ifdef HAVE_GETOPT_LONG -# include -# else -# include "compat/getopt.h" -#endif /* HAVE_GETOPT_LONG */ - -#include "sudoers.h" -#include "sudoers_version.h" -#include "sudo_lbuf.h" -#include "redblack.h" -#include "cvtsudoers.h" -#include - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (size < 5) { - return 0; - } - - char filename[256]; - sprintf(filename, "/tmp/fuzz-sudoers.XXXXXX"); - - int fp = mkstemp(filename); - if (fp < 0) { - return 0; - } - write(fp, data, size); - close(fp); - - // main entry point for the fuzzer - FILE *fd = fopen(filename, "rb"); - if (fd == NULL) { - return 0; - } - - init_parser(filename, false, true); - sudoers_parse_ldif(&parsed_policy, fd, NULL, true); - - remove(filename); - return 0; -}