diff options
author | Theodore Ts'o <tytso@mit.edu> | 2022-08-06 18:35:30 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2022-08-09 19:45:07 -0400 |
commit | 2869485be9b1b94b93a50589de52ca553e5a116d (patch) | |
tree | f5562f9f850f5a1788638fcc27c2627c9a758178 | |
parent | 27504bcf89193d47d7632cde922a65e0c051be01 (diff) | |
download | e2fsprogs-2869485be9b1b94b93a50589de52ca553e5a116d.tar.gz |
Build the fuzzers from oss-fuzz
The fuzzers from oss-fuzz in projects/e2fsprogs/fuzz (as of commit
78ecd3f07fca with some slight modifications for better error
reporting) have been placed in the tests/fuzz directory and the
configure script now supports a new option --enable-fuzzing which will
build these fuzzers using clang's -fsanitize=fuzzer command line
option.
In general, some sanitizer such as --enable-addrsan or --enable-ubsan
(to enable ASAN or UBSAN, respectively) should be enabled alongside
--enable-fuzzing.
A typical configure command to build the fuzzers might be:
configure CC=clang CXX=clang++ CFLAGS=-g --enable-fuzzing --enable-addrsan
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | MCONFIG.in | 3 | ||||
-rw-r--r-- | Makefile.in | 4 | ||||
-rwxr-xr-x | configure | 715 | ||||
-rw-r--r-- | configure.ac | 42 | ||||
-rw-r--r-- | depfix.sed | 2 | ||||
-rw-r--r-- | lib/support/Makefile.in | 2 | ||||
-rw-r--r-- | lib/support/print_fs_flags.c | 75 | ||||
-rw-r--r-- | lib/support/print_fs_flags.h | 5 | ||||
-rw-r--r-- | tests/fuzz/.gitignore | 3 | ||||
-rw-r--r-- | tests/fuzz/Makefile.in | 83 | ||||
-rw-r--r-- | tests/fuzz/ext2fs_check_directory_fuzzer.cc | 43 | ||||
-rw-r--r-- | tests/fuzz/ext2fs_image_read_write_fuzzer.cc | 135 | ||||
-rw-r--r-- | tests/fuzz/ext2fs_read_bitmap_fuzzer.cc | 108 |
13 files changed, 1214 insertions, 6 deletions
diff --git a/MCONFIG.in b/MCONFIG.in index 3fede36df..82c75a28e 100644 --- a/MCONFIG.in +++ b/MCONFIG.in @@ -87,6 +87,7 @@ SANITIZER_CFLAGS = @lto_cflags@ @ubsan_cflags@ @addrsan_cflags@ @threadsan_cflag SANITIZER_LDFLAGS = @lto_ldflags@ @ubsan_ldflags@ @addrsan_ldflags@ @threadsan_ldflags@ CC = @PTHREAD_CC@ +CXX = @CXX@ BUILD_CC = @BUILD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -99,7 +100,7 @@ ALL_CFLAGS_SHLIB = $(CPPFLAGS) $(SANITIZER_CFLAGS) $(CFLAGS_SHLIB) $(PTHREAD_CFL ALL_CFLAGS_STLIB = $(CPPFLAGS) $(SANITIZER_CFLAGS) $(CFLAGS_STLIB) $(PTHREAD_CFLAGS) $(CFLAGS_WARN) @DEFS@ $(LOCAL_CFLAGS) LDFLAGS = $(SANITIZER_LDFLAGS) $(PTHREAD_CFLAGS) @LDFLAGS@ LDFLAGS_SHLIB = $(SANITIZER_LDFLAGS) $(PTHREAD_CFLAGS) @LDFLAGS_SHLIB@ -ALL_LDFLAGS = $(LDFLAGS) @LDFLAG_DYNAMIC@ +ALL_LDFLAGS = $(LDFLAGS) @LDFLAG_DYNAMIC@ $(LOCAL_LDFLAGS) LDFLAGS_STATIC = $(SANITIZER_LDFLAGS) $(PTHREAD_CFLAGS) @LDFLAGS_STATIC@ BUILD_CFLAGS = $(SANITIZER_CFLAGS) @BUILD_CFLAGS@ BUILD_LDFLAGS = $(SANITIZER_LDFLAGS) @BUILD_LDFLAGS@ diff --git a/Makefile.in b/Makefile.in index d412dfbce..79b711650 100644 --- a/Makefile.in +++ b/Makefile.in @@ -22,8 +22,8 @@ MKDIR_P = @MKDIR_P@ LIB_SUBDIRS=lib/et lib/ss $(E2P_LIB_SUBDIR) $(UUID_LIB_SUBDIR) \ $(BLKID_LIB_SUBDIR) $(SUPPORT_LIB_SUBDIR) $(EXT2FS_LIB_SUBDIR) -PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs po \ - $(E2SCRUB_DIR) +PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs \ + tests/fuzz po $(E2SCRUB_DIR) SUBDIRS=util $(LIB_SUBDIRS) $(PROG_SUBDIRS) tests @@ -678,6 +678,13 @@ E2SCRUB_CMT UNIX_CMT CYGWIN_CMT LINUX_CMT +FUZZING_CMT +fuzzer_ldflags +fuzzer_cflags +have_fuzzer +ac_ct_CXX +CXXFLAGS +CXX threadsan_ldflags threadsan_cflags have_threadsan @@ -923,6 +930,7 @@ enable_lto enable_ubsan enable_addrsan enable_threadsan +enable_fuzzing with_multiarch with_udev_rules_dir with_crond_dir @@ -940,6 +948,9 @@ CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR +CXX +CXXFLAGS +CCC udev_CFLAGS udev_LIBS systemd_CFLAGS @@ -1609,6 +1620,7 @@ Optional Features: --enable-ubsan enable undefined behavior sanitizer --enable-addrsan enable address sanitizer --enable-threadsan enable thread sanitizer + --enable-fuzzing enable fuzzing sanitizer Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1647,6 +1659,8 @@ Some influential environment variables: directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path + CXX C++ compiler command + CXXFLAGS C++ compiler flags udev_CFLAGS C compiler flags for udev, overriding pkg-config udev_LIBS linker flags for udev, overriding pkg-config systemd_CFLAGS @@ -2354,6 +2368,45 @@ rm -f conftest.val as_fn_set_status $ac_retval } # ac_fn_c_compute_int + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile ac_configure_args_raw= for ac_arg do @@ -2970,6 +3023,222 @@ as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H" as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H" gt_needs="$gt_needs " as_fn_append ac_func_c_list " vprintf HAVE_VPRINTF" +# Test code for whether the C++ compiler supports C++98 (global declarations) +ac_cxx_conftest_cxx98_globals=' +// Does the compiler advertise C++98 conformance? +#if !defined __cplusplus || __cplusplus < 199711L +# error "Compiler does not advertise C++98 conformance" +#endif + +// These inclusions are to reject old compilers that +// lack the unsuffixed header files. +#include <cstdlib> +#include <exception> + +// <cassert> and <cstring> are *not* freestanding headers in C++98. +extern void assert (int); +namespace std { + extern int strcmp (const char *, const char *); +} + +// Namespaces, exceptions, and templates were all added after "C++ 2.0". +using std::exception; +using std::strcmp; + +namespace { + +void test_exception_syntax() +{ + try { + throw "test"; + } catch (const char *s) { + // Extra parentheses suppress a warning when building autoconf itself, + // due to lint rules shared with more typical C programs. + assert (!(strcmp) (s, "test")); + } +} + +template <typename T> struct test_template +{ + T const val; + explicit test_template(T t) : val(t) {} + template <typename U> T add(U u) { return static_cast<T>(u) + val; } +}; + +} // anonymous namespace +' + +# Test code for whether the C++ compiler supports C++98 (body of main) +ac_cxx_conftest_cxx98_main=' + assert (argc); + assert (! argv[0]); +{ + test_exception_syntax (); + test_template<double> tt (2.0); + assert (tt.add (4) == 6.0); + assert (true && !false); +} +' + +# Test code for whether the C++ compiler supports C++11 (global declarations) +ac_cxx_conftest_cxx11_globals=' +// Does the compiler advertise C++ 2011 conformance? +#if !defined __cplusplus || __cplusplus < 201103L +# error "Compiler does not advertise C++11 conformance" +#endif + +namespace cxx11test +{ + constexpr int get_val() { return 20; } + + struct testinit + { + int i; + double d; + }; + + class delegate + { + public: + delegate(int n) : n(n) {} + delegate(): delegate(2354) {} + + virtual int getval() { return this->n; }; + protected: + int n; + }; + + class overridden : public delegate + { + public: + overridden(int n): delegate(n) {} + virtual int getval() override final { return this->n * 2; } + }; + + class nocopy + { + public: + nocopy(int i): i(i) {} + nocopy() = default; + nocopy(const nocopy&) = delete; + nocopy & operator=(const nocopy&) = delete; + private: + int i; + }; + + // for testing lambda expressions + template <typename Ret, typename Fn> Ret eval(Fn f, Ret v) + { + return f(v); + } + + // for testing variadic templates and trailing return types + template <typename V> auto sum(V first) -> V + { + return first; + } + template <typename V, typename... Args> auto sum(V first, Args... rest) -> V + { + return first + sum(rest...); + } +} +' + +# Test code for whether the C++ compiler supports C++11 (body of main) +ac_cxx_conftest_cxx11_main=' +{ + // Test auto and decltype + auto a1 = 6538; + auto a2 = 48573953.4; + auto a3 = "String literal"; + + int total = 0; + for (auto i = a3; *i; ++i) { total += *i; } + + decltype(a2) a4 = 34895.034; +} +{ + // Test constexpr + short sa[cxx11test::get_val()] = { 0 }; +} +{ + // Test initializer lists + cxx11test::testinit il = { 4323, 435234.23544 }; +} +{ + // Test range-based for + int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, + 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + for (auto &x : array) { x += 23; } +} +{ + // Test lambda expressions + using cxx11test::eval; + assert (eval ([](int x) { return x*2; }, 21) == 42); + double d = 2.0; + assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); + assert (d == 5.0); + assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); + assert (d == 5.0); +} +{ + // Test use of variadic templates + using cxx11test::sum; + auto a = sum(1); + auto b = sum(1, 2); + auto c = sum(1.0, 2.0, 3.0); +} +{ + // Test constructor delegation + cxx11test::delegate d1; + cxx11test::delegate d2(); + cxx11test::delegate d3(45); +} +{ + // Test override and final + cxx11test::overridden o1(55464); +} +{ + // Test nullptr + char *c = nullptr; +} +{ + // Test template brackets + test_template<::test_template<int>> v(test_template<int>(12)); +} +{ + // Unicode literals + char const *utf8 = u8"UTF-8 string \u2500"; + char16_t const *utf16 = u"UTF-8 string \u2500"; + char32_t const *utf32 = U"UTF-32 string \u2500"; +} +' + +# Test code for whether the C compiler supports C++11 (complete). +ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} +${ac_cxx_conftest_cxx11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + ${ac_cxx_conftest_cxx11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C++98 (complete). +ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + return ok; +} +" + # Auxiliary files required by this configure script. ac_aux_files="config.rpath install-sh config.guess config.sub" @@ -14091,6 +14360,449 @@ if test "$have_threadsan" = "yes" && test "$have_addrsan" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ADDRSAN and THREADSAN are not known to work together." >&5 printf "%s\n" "$as_me: WARNING: ADDRSAN and THREADSAN are not known to work together." >&2;} fi +FUZZING_CMT="#" +# Check whether --enable-fuzzing was given. +if test ${enable_fuzzing+y} +then : + enableval=$enable_fuzzing; +else $as_nop + enable_fuzzing=no +fi + +if test "$enable_fuzzing" = "yes" || test "$enable_fuzzing" = "probe"; then + + + + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +printf "%s\n" "$CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +printf "%s\n" "$ac_ct_CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 +printf %s "checking whether the compiler supports GNU C++... " >&6; } +if test ${ac_cv_cxx_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_compiler_gnu=yes +else $as_nop + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+y} +ac_save_CXXFLAGS=$CXXFLAGS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +printf %s "checking whether $CXX accepts -g... " >&6; } +if test ${ac_cv_prog_cxx_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_g=yes +else $as_nop + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + +else $as_nop + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } +if test $ac_test_CXXFLAGS; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_prog_cxx_stdcxx=no +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 +printf %s "checking for $CXX option to enable C++11 features... " >&6; } +if test ${ac_cv_prog_cxx_11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_11=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx11_program +_ACEOF +for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx11" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx11" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 + ac_prog_cxx_stdcxx=cxx11 +fi +fi +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 +printf %s "checking for $CXX option to enable C++98 features... " >&6; } +if test ${ac_cv_prog_cxx_98+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_98=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx98_program +_ACEOF +for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx98=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx98" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx98" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx98" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx98" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 + ac_prog_cxx_stdcxx=cxx98 +fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports fuzzing sanitizer" >&5 +printf %s "checking if C compiler supports fuzzing sanitizer... " >&6; } + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + OLD_CXXFLAGS="$CXXFLAGS" + OLD_LDFLAGS="$LDFLAGS" + FUZZER_FLAGS="-fsanitize=fuzzer" + CXXFLAGS="$CXXFLAGS $FUZZER_FLAGS" + LDFLAGS="$LDFLAGS $FUZZER_FLAGS" + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include <stddef.h> + #include <stdint.h> + +int +main (void) +{ + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + fuzzer_cflags=$FUZZER_FLAGS + fuzzer_ldflags=$FUZZER_FLAGS + FUZZING_CMT= + have_fuzzer=yes +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + as_fn_error $? "fuzzing requested but not available" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CXXFLAGS="${OLD_CXXFLAGS}" + LDFLAGS="${OLD_LDFLAGS}" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +fi +if test "$enable_fuzzer" = "yes" && test "$have_fuzzer" != "yes"; then + as_fn_error $? "Fuzzing not supported by compiler." "$LINENO" 5 +fi + LINUX_CMT="#" CYGWIN_CMT="#" UNIX_CMT= @@ -14584,7 +15296,8 @@ for i in MCONFIG Makefile \ lib/ss/ss.pc lib/et/com_err.pc lib/e2p/e2p.pc lib/ext2fs/ext2fs.pc \ misc/Makefile ext2ed/Makefile e2fsck/Makefile \ debugfs/Makefile tests/Makefile tests/progs/Makefile \ - resize/Makefile doc/Makefile po/Makefile.in scrub/Makefile; do + tests/fuzz/Makefile resize/Makefile doc/Makefile \ + po/Makefile.in scrub/Makefile; do if test -d `dirname ${srcdir}/$i` ; then outlist="$outlist $i" fi diff --git a/configure.ac b/configure.ac index cb528da68..78f71fd8e 100644 --- a/configure.ac +++ b/configure.ac @@ -1495,6 +1495,45 @@ if test "$have_threadsan" = "yes" && test "$have_addrsan" = "yes"; then AC_MSG_WARN([ADDRSAN and THREADSAN are not known to work together.]) fi dnl +dnl Enable the fuzzer sanitizer for all packages +dnl +FUZZING_CMT="#" +AC_ARG_ENABLE([fuzzing], +AS_HELP_STRING([--enable-fuzzing],[enable fuzzing sanitizer]),, +enable_fuzzing=no) +if test "$enable_fuzzing" = "yes" || test "$enable_fuzzing" = "probe"; then + AC_PROG_CXX + AC_MSG_CHECKING([if C compiler supports fuzzing sanitizer]) + AC_LANG_PUSH([C++]) + OLD_CXXFLAGS="$CXXFLAGS" + OLD_LDFLAGS="$LDFLAGS" + FUZZER_FLAGS="-fsanitize=fuzzer" + CXXFLAGS="$CXXFLAGS $FUZZER_FLAGS" + LDFLAGS="$LDFLAGS $FUZZER_FLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include <stddef.h> + #include <stdint.h> + ]], + [ return 0; ])], + [AC_MSG_RESULT([yes])] + [fuzzer_cflags=$FUZZER_FLAGS] + [fuzzer_ldflags=$FUZZER_FLAGS] + [FUZZING_CMT=] + [have_fuzzer=yes], + [AC_MSG_RESULT([no])] + [AC_MSG_ERROR([fuzzing requested but not available])]) + CXXFLAGS="${OLD_CXXFLAGS}" + LDFLAGS="${OLD_LDFLAGS}" + AC_LANG_POP([C++]) + AC_SUBST(have_fuzzer) + AC_SUBST(fuzzer_cflags) + AC_SUBST(fuzzer_ldflags) +fi +if test "$enable_fuzzer" = "yes" && test "$have_fuzzer" != "yes"; then + AC_MSG_ERROR([Fuzzing not supported by compiler.]) +fi +AC_SUBST(FUZZING_CMT) +dnl dnl OS-specific uncomment control dnl LINUX_CMT="#" @@ -1819,7 +1858,8 @@ for i in MCONFIG Makefile \ lib/ss/ss.pc lib/et/com_err.pc lib/e2p/e2p.pc lib/ext2fs/ext2fs.pc \ misc/Makefile ext2ed/Makefile e2fsck/Makefile \ debugfs/Makefile tests/Makefile tests/progs/Makefile \ - resize/Makefile doc/Makefile po/Makefile.in scrub/Makefile; do + tests/fuzz/Makefile resize/Makefile doc/Makefile \ + po/Makefile.in scrub/Makefile; do if test -d `dirname ${srcdir}/$i` ; then outlist="$outlist $i" fi diff --git a/depfix.sed b/depfix.sed index 582d79fd9..680fb2200 100644 --- a/depfix.sed +++ b/depfix.sed @@ -24,7 +24,7 @@ s/ */ /g s;/usr/include/[^ ]* *;;g s;/usr/lib/[^ ]* *;;g -s;/mit/cygnus[^ ]* *;;g +s;/bin/[^ ]* *;;g s;\.\./[^ ]*lib/blkid/blkid[^ ]* *;;g s;\.\./[^ ]*lib/uuid/uuid.h[^ ]* *;;g diff --git a/lib/support/Makefile.in b/lib/support/Makefile.in index f3c7981e4..e5600a82a 100644 --- a/lib/support/Makefile.in +++ b/lib/support/Makefile.in @@ -18,6 +18,7 @@ OBJS= cstring.o \ plausible.o \ profile.o \ parse_qtype.o \ + print_fs_flags.o \ profile_helpers.o \ prof_err.o \ quotaio.o \ @@ -30,6 +31,7 @@ SRCS= $(srcdir)/argv_parse.c \ $(srcdir)/mkquota.c \ $(srcdir)/parse_qtype.c \ $(srcdir)/plausible.c \ + $(srcdir)/print_fs_flags.c \ $(srcdir)/profile.c \ $(srcdir)/profile_helpers.c \ prof_err.c \ diff --git a/lib/support/print_fs_flags.c b/lib/support/print_fs_flags.c new file mode 100644 index 000000000..e54acc04b --- /dev/null +++ b/lib/support/print_fs_flags.c @@ -0,0 +1,75 @@ +/* + * print_flags.c - Print ext2_filsys flags + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include <stdio.h> + +#include "ext2fs/ext2fs.h" + +struct flags_name { + unsigned long flag; + const char *name; +}; + +static struct flags_name flags_array[] = { + EXT2_FLAG_RW, "EXT2_FLAG_RW", + EXT2_FLAG_CHANGED, "EXT2_FLAG_CHANGED", + EXT2_FLAG_DIRTY, "EXT2_FLAG_DIRTY", + EXT2_FLAG_VALID, "EXT2_FLAG_VALID", + EXT2_FLAG_IB_DIRTY, "EXT2_FLAG_IB_DIRTY", + EXT2_FLAG_BB_DIRTY, "EXT2_FLAG_BB_DIRTY", + EXT2_FLAG_SWAP_BYTES, "EXT2_FLAG_SWAP_BYTES", + EXT2_FLAG_SWAP_BYTES_READ, "EXT2_FLAG_SWAP_BYTES_READ", + EXT2_FLAG_SWAP_BYTES_WRITE, "EXT2_FLAG_SWAP_BYTES_WRITE", + EXT2_FLAG_MASTER_SB_ONLY, "EXT2_FLAG_MASTER_SB_ONLY", + EXT2_FLAG_FORCE, "EXT2_FLAG_FORCE", + EXT2_FLAG_SUPER_ONLY, "EXT2_FLAG_SUPER_ONLY", + EXT2_FLAG_JOURNAL_DEV_OK, "EXT2_FLAG_JOURNAL_DEV_OK", + EXT2_FLAG_IMAGE_FILE, "EXT2_FLAG_IMAGE_FILE", + EXT2_FLAG_EXCLUSIVE, "EXT2_FLAG_EXCLUSIVE", + EXT2_FLAG_SOFTSUPP_FEATURES, "EXT2_FLAG_SOFTSUPP_FEATURES", + EXT2_FLAG_NOFREE_ON_ERROR, "EXT2_FLAG_NOFREE_ON_ERROR", + EXT2_FLAG_64BITS, "EXT2_FLAG_64BITS", + EXT2_FLAG_PRINT_PROGRESS, "EXT2_FLAG_PRINT_PROGRESS", + EXT2_FLAG_DIRECT_IO, "EXT2_FLAG_DIRECT_IO", + EXT2_FLAG_SKIP_MMP, "EXT2_FLAG_SKIP_MMP", + EXT2_FLAG_IGNORE_CSUM_ERRORS, "EXT2_FLAG_IGNORE_CSUM_ERRORS", + EXT2_FLAG_SHARE_DUP, "EXT2_FLAG_SHARE_DUP", + EXT2_FLAG_IGNORE_SB_ERRORS, "EXT2_FLAG_IGNORE_SB_ERRORS", + EXT2_FLAG_BBITMAP_TAIL_PROBLEM, "EXT2_FLAG_BBITMAP_TAIL_PROBLEM", + EXT2_FLAG_IBITMAP_TAIL_PROBLEM, "EXT2_FLAG_IBITMAP_TAIL_PROBLEM", + EXT2_FLAG_THREADS, "EXT2_FLAG_THREADS", + 0 +}; + +void print_fs_flags(FILE * f, unsigned long flags) +{ + struct flags_name *fp; + int first = 1, pos = 16; + + for (fp = flags_array; fp->flag != 0; fp++) { + if ((flags & fp->flag) == 0) + continue; + pos += strlen(fp->name) + 1; + if (pos > 72) { + fputs("\n\t", f); + pos = 9 + strlen(fp->name); + } + if (first) + first = 0; + else + fputc(' ', f); + fputs(fp->name, f); + } + fputc('\n', f); +} diff --git a/lib/support/print_fs_flags.h b/lib/support/print_fs_flags.h new file mode 100644 index 000000000..bdd58a00a --- /dev/null +++ b/lib/support/print_fs_flags.h @@ -0,0 +1,5 @@ +/* + * print_flags.h -- header file for printing the fs flags + */ + +void print_fs_flags(FILE * f, unsigned long flags); diff --git a/tests/fuzz/.gitignore b/tests/fuzz/.gitignore new file mode 100644 index 000000000..381b20a12 --- /dev/null +++ b/tests/fuzz/.gitignore @@ -0,0 +1,3 @@ +ext2fs_check_directory_fuzzer +ext2fs_image_read_write_fuzzer +ext2fs_read_bitmap_fuzzer diff --git a/tests/fuzz/Makefile.in b/tests/fuzz/Makefile.in new file mode 100644 index 000000000..a6d80639f --- /dev/null +++ b/tests/fuzz/Makefile.in @@ -0,0 +1,83 @@ +# +# Makefile for the tests/fuzz directory +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +top_builddir = ../.. +my_dir = tests/fuzz + +@MCONFIG@ + +PROGS= ext2fs_check_directory_fuzzer \ + ext2fs_image_read_write_fuzzer \ + ext2fs_read_bitmap_fuzzer + +SRCS= $(srcdir)/ext2fs_check_directory_fuzzer.cc \ + $(srcdir)/ext2fs_image_read_write_fuzzer.cc \ + $(srcdir)/ext2fs_read_bitmap_fuzzer.cc + +LOCAL_CFLAGS= @fuzzer_cflags@ +LOCAL_LDFLAGS= @fuzzer_ldflags@ + +LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBSUPPORT) +DEPLIBS= $(LIBEXT2FS) $(DEPLIBCOM_ERR) $(DEPLIBSUPPORT) + +STATIC_LIBS= $(LIBSUPPORT) $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) \ + $(STATIC_LIBCOM_ERR) +STATIC_DEPLIBS= $(DEPLIBSUPPORT) $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) \ + $(DEPSTATIC_LIBCOM_ERR) + +FUZZ_LDFLAGS= $(ALL_LDFLAGS) +FUZZ_DEP= $(STATIC_DEPLIBS) $(srcdir)/Makefile.in + +.cc.o: + $(E) " CXX $<" + $(Q) $(CXX) -c $(ALL_CFLAGS) $< -o $@ + +@FUZZING_CMT@all:: $(PROGS) + +clean:: + $(RM) -f $(PROGS) *.o + +ext2fs_check_directory_fuzzer: ext2fs_check_directory_fuzzer.o $(FUZZ_DEP) + $(E) " LD $@" + $(Q) $(CXX) $(FUZZ_LDFLAGS) -o $@ $< $(STATIC_LIBS) $(SYSLIBS) + +ext2fs_image_read_write_fuzzer: ext2fs_image_read_write_fuzzer.o $(FUZZ_DEP) + $(E) " LD $@" + $(Q) $(CXX) $(FUZZ_LDFLAGS) -o $@ $< $(STATIC_LIBS) $(SYSLIBS) + +ext2fs_read_bitmap_fuzzer: ext2fs_read_bitmap_fuzzer.o $(FUZZ_DEP) + $(E) " LD $@" + $(Q) $(CXX) $(FUZZ_LDFLAGS) -o $@ $< $(STATIC_LIBS) $(SYSLIBS) + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# +ext2fs_check_directory_fuzzer.o: $(srcdir)/ext2fs_check_directory_fuzzer.cc \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \ + $(top_srcdir)/lib/ext2fs/bitops.h +ext2fs_image_read_write_fuzzer.o: $(srcdir)/ext2fs_image_read_write_fuzzer.cc \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \ + $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/e2p/e2p.h \ + $(top_srcdir)/lib/support/print_fs_flags.h +ext2fs_read_bitmap_fuzzer.o: $(srcdir)/ext2fs_read_bitmap_fuzzer.cc \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \ + $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/e2p/e2p.h \ + $(top_srcdir)/lib/support/print_fs_flags.h diff --git a/tests/fuzz/ext2fs_check_directory_fuzzer.cc b/tests/fuzz/ext2fs_check_directory_fuzzer.cc new file mode 100644 index 000000000..61cf42fa5 --- /dev/null +++ b/tests/fuzz/ext2fs_check_directory_fuzzer.cc @@ -0,0 +1,43 @@ +// Copyright 2020 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 <stddef.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> + +#include "ext2fs/ext2fs.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + static const char* fname = "/tmp/ext2_test_file"; + + // Write our data to a temp file. + int fd = open(fname, O_RDWR|O_CREAT|O_TRUNC); + write(fd, data, size); + close(fd); + + ext2_filsys fs; + errcode_t retval = ext2fs_open( + fname, + EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0, + unix_io_manager, + &fs); + + if (!retval) { + retval = ext2fs_check_directory(fs, EXT2_ROOT_INO); + ext2fs_close(fs); + } + + return 0; +} diff --git a/tests/fuzz/ext2fs_image_read_write_fuzzer.cc b/tests/fuzz/ext2fs_image_read_write_fuzzer.cc new file mode 100644 index 000000000..8aa0cb845 --- /dev/null +++ b/tests/fuzz/ext2fs_image_read_write_fuzzer.cc @@ -0,0 +1,135 @@ +// Copyright 2020 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. + +// #define USE_FLAGS +// #define DUMP_SUPER +// #define SAVE_FS_IMAGE + +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <sys/syscall.h> +#include <linux/memfd.h> +#include <fuzzer/FuzzedDataProvider.h> + +#include "ext2fs/ext2fs.h" +extern "C" { +#include "e2p/e2p.h" +#include "support/print_fs_flags.h" +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + + const char *progname = "ext2fs_image_read_write_fuzzer"; + add_error_table(&et_ext2_error_table); + + enum FuzzerType { + ext2fsImageBitmapRead, + ext2fsImageInodeRead, + ext2fsImageSuperRead, + ext2fsImageBitmapWrite, + ext2fsImageInodeWrite, + ext2fsImageSuperWrite, + kMaxValue = ext2fsImageSuperWrite + }; + + FuzzedDataProvider stream(data, size); + const FuzzerType f = stream.ConsumeEnum<FuzzerType>(); + int flags = stream.ConsumeIntegral<int>(); +#ifndef USE_FLAGS + flags = 0; +#endif + + static const char* fname = "/tmp/ext2_test_file"; + + // Write our data to a temp file. +#ifdef SAVE_FS_IMAGE + int fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0644); +#else + int fd = syscall(SYS_memfd_create, fname, 0); +#endif + std::vector<char> buffer = stream.ConsumeRemainingBytes<char>(); + write(fd, buffer.data(), buffer.size()); + + std::string fspath("/proc/self/fd/" + std::to_string(fd)); + + ext2_filsys fs; +#ifdef USE_FLAGS + printf("Flags: 0x%08x ", flags); + print_fs_flags(stdout, flags); + flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; +#endif + errcode_t retval = ext2fs_open( + fspath.c_str(), + flags | EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0, + unix_io_manager, + &fs); + + if (retval) { + com_err(progname, retval, "while trying to open file system"); + } else { +#ifdef DUMP_SUPER + list_super2(fs->super, stdout); +#endif + printf("FuzzerType: %d\n", (int) f); + switch (f) { + case ext2fsImageBitmapRead: { + retval = ext2fs_image_bitmap_read(fs, fd, 0); + if (retval) + com_err(progname, retval, "while trying to read image bitmap"); + break; + } + case ext2fsImageInodeRead: { + retval = ext2fs_image_inode_read(fs, fd, 0); + if (retval) + com_err(progname, retval, "while trying to read image inode"); + break; + } + case ext2fsImageSuperRead: { + retval = ext2fs_image_super_read(fs, fd, 0); + if (retval) + com_err(progname, retval, "while trying to read image superblock"); + break; + } + case ext2fsImageBitmapWrite: { + retval = ext2fs_image_bitmap_write(fs, fd, 0); + if (retval) + com_err(progname, retval, "while trying to write image bitmap"); + break; + } + case ext2fsImageInodeWrite: { + retval = ext2fs_image_inode_write(fs, fd, 0); + if (retval) + com_err(progname, retval, "while trying to write image inode"); + break; + } + case ext2fsImageSuperWrite: { + retval = ext2fs_image_super_write(fs, fd, 0); + if (retval) + com_err(progname, retval, "while trying to write image superblock"); + break; + } + default: { + assert(false); + } + } + ext2fs_close(fs); + } + close(fd); + + return 0; +} diff --git a/tests/fuzz/ext2fs_read_bitmap_fuzzer.cc b/tests/fuzz/ext2fs_read_bitmap_fuzzer.cc new file mode 100644 index 000000000..fa3d7e7d2 --- /dev/null +++ b/tests/fuzz/ext2fs_read_bitmap_fuzzer.cc @@ -0,0 +1,108 @@ +// Copyright 2020 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. + +// #define USE_FLAGS +// #define DUMP_SUPER +// #define SAVE_FS_IMAGE + +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <sys/syscall.h> +#include <linux/memfd.h> +#include <fuzzer/FuzzedDataProvider.h> + +#include "ext2fs/ext2fs.h" +extern "C" { +#include "e2p/e2p.h" +#include "support/print_fs_flags.h" +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + + const char *progname = "ext2fs_read_bitmap_fuzzer"; + add_error_table(&et_ext2_error_table); + + enum FuzzerType { + ext2fsReadBlockBitmap, + ext2fsReadInodeBitmap, + kMaxValue = ext2fsReadInodeBitmap + }; + + FuzzedDataProvider stream(data, size); + const FuzzerType f = stream.ConsumeEnum<FuzzerType>(); + int flags = stream.ConsumeIntegral<int>(); +#ifndef USE_FLAGS + flags = 0; +#endif + + static const char* fname = "/tmp/ext2_test_file"; + + // Write our data to a temp file. +#ifdef SAVE_FS_IMAGE + int fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0644); +#else + int fd = syscall(SYS_memfd_create, fname, 0); +#endif + std::vector<char> buffer = stream.ConsumeRemainingBytes<char>(); + write(fd, buffer.data(), buffer.size()); + + std::string fspath("/proc/self/fd/" + std::to_string(fd)); + + ext2_filsys fs; +#ifdef USE_FLAGS + printf("Flags: 0x%08x ", flags); + print_fs_flags(stdout, flags); + flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; +#endif + errcode_t retval = ext2fs_open( + fspath.c_str(), + flags | EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0, + unix_io_manager, + &fs); + + if (retval) { + com_err(progname, retval, "while trying to open file system"); + } else { +#ifdef DUMP_SUPER + list_super2(fs->super, stdout); +#endif + switch (f) { + case ext2fsReadBlockBitmap: { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + com_err(progname, retval, "while trying to read block bitmap"); + break; + } + case ext2fsReadInodeBitmap: { + retval = ext2fs_read_inode_bitmap(fs); + if (retval) + com_err(progname, retval, "while trying to read inode bitmap"); + break; + } + default: { + assert(false); + } + } + retval = ext2fs_close(fs); + if (retval) + com_err(progname, retval, "while trying to close file system"); + } + close(fd); + + return 0; +} |