sudoers: use in-tree fuzzers and add new one for the sudoers parser (#5089)

This commit is contained in:
Todd C. Miller 2021-02-02 16:59:02 -07:00 committed by GitHub
parent e518f6e22e
commit 1ca56df17e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 156 deletions

View File

@ -19,4 +19,3 @@ RUN git clone https://github.com/sudo-project/sudo
WORKDIR $SRC/sudo
COPY build.sh $SRC/
COPY fuzz_* $SRC/

View File

@ -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

View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif /* HAVE_STDBOOL_H */
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <limits.h>
#include <fcntl.h>
#include <time.h>
#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;
}

View File

@ -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 <stdint.h>
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <unistd.h>
#ifdef HAVE_GETOPT_LONG
# include <getopt.h>
# 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 <gram.h>
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;
}