From 31e57a35dc7f34556fe66c4a661729a37f966814 Mon Sep 17 00:00:00 2001 From: Jonathan Rudenberg Date: Tue, 16 Jan 2018 10:25:43 -0500 Subject: [PATCH] fuzz: allow building fuzzers outside of oss-fuzz Add a new -Dllvm-fuzz=true option that can be used to build against libFuzzer and update the oss-fuzz script to work outside of the oss-fuzz build environment. --- meson.build | 74 +++++++++++++++++++++++++-------------------- meson_options.txt | 2 ++ scripts/oss-fuzz.sh | 24 +++++++++++---- 3 files changed, 61 insertions(+), 39 deletions(-) diff --git a/meson.build b/meson.build index df79a54026..2e3898b3b1 100644 --- a/meson.build +++ b/meson.build @@ -268,8 +268,16 @@ if get_option('tests') != 'false' endif endif -ossfuzz = get_option('oss-fuzz') -if ossfuzz +want_ossfuzz = get_option('oss-fuzz') +want_libfuzzer = get_option('llvm-fuzz') +fuzzer_build = want_ossfuzz or want_libfuzzer +if want_ossfuzz and want_libfuzzer + error('only one of oss-fuzz and llvm-fuzz can be specified') +endif +if want_libfuzzer + fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer') +endif +if want_ossfuzz fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine') endif @@ -316,7 +324,7 @@ endforeach # the oss-fuzz fuzzers are not built with -fPIE, so don't # enable it when we are linking against them -if not ossfuzz +if not fuzzer_build if cc.has_argument('-fPIE') add_project_arguments('-fPIE', language : 'c') endif @@ -372,7 +380,7 @@ foreach arg : ['-Wl,-z,relro', cc.cmd_array(), '-x', 'c', arg, '-include', link_test_c).returncode() == 0 message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no')) - if have and (arg != '-pie' or not ossfuzz) + if have and (arg != '-pie' or not fuzzer_build) add_project_link_arguments(arg, language : 'c') endif endforeach @@ -780,10 +788,10 @@ endif libmount = dependency('mount', version : '>= 2.30', - required : not ossfuzz) + required : not fuzzer_build) want_seccomp = get_option('seccomp') -if want_seccomp != 'false' and not ossfuzz +if want_seccomp != 'false' and not fuzzer_build libseccomp = dependency('libseccomp', version : '>= 2.3.1', required : want_seccomp == 'true') @@ -796,7 +804,7 @@ conf.set10('HAVE_SECCOMP', have) m4_defines += have ? ['-DHAVE_SECCOMP'] : [] want_selinux = get_option('selinux') -if want_selinux != 'false' and not ossfuzz +if want_selinux != 'false' and not fuzzer_build libselinux = dependency('libselinux', version : '>= 2.1.9', required : want_selinux == 'true') @@ -809,7 +817,7 @@ conf.set10('HAVE_SELINUX', have) m4_defines += have ? ['-DHAVE_SELINUX'] : [] want_apparmor = get_option('apparmor') -if want_apparmor != 'false' and not ossfuzz +if want_apparmor != 'false' and not fuzzer_build libapparmor = dependency('libapparmor', required : want_apparmor == 'true') have = libapparmor.found() @@ -829,7 +837,7 @@ endif want_polkit = get_option('polkit') install_polkit = false install_polkit_pkla = false -if want_polkit != 'false' and not ossfuzz +if want_polkit != 'false' and not fuzzer_build install_polkit = true libpolkit = dependency('polkit-gobject-1', @@ -842,7 +850,7 @@ endif conf.set10('ENABLE_POLKIT', install_polkit) want_acl = get_option('acl') -if want_acl != 'false' and not ossfuzz +if want_acl != 'false' and not fuzzer_build libacl = cc.find_library('acl', required : want_acl == 'true') have = libacl.found() else @@ -853,7 +861,7 @@ conf.set10('HAVE_ACL', have) m4_defines += have ? ['-DHAVE_ACL'] : [] want_audit = get_option('audit') -if want_audit != 'false' and not ossfuzz +if want_audit != 'false' and not fuzzer_build libaudit = dependency('audit', required : want_audit == 'true') have = libaudit.found() else @@ -863,7 +871,7 @@ endif conf.set10('HAVE_AUDIT', have) want_blkid = get_option('blkid') -if want_blkid != 'false' and not ossfuzz +if want_blkid != 'false' and not fuzzer_build libblkid = dependency('blkid', required : want_blkid == 'true') have = libblkid.found() else @@ -873,7 +881,7 @@ endif conf.set10('HAVE_BLKID', have) want_kmod = get_option('kmod') -if want_kmod != 'false' and not ossfuzz +if want_kmod != 'false' and not fuzzer_build libkmod = dependency('libkmod', version : '>= 15', required : want_kmod == 'true') @@ -885,7 +893,7 @@ endif conf.set10('HAVE_KMOD', have) want_pam = get_option('pam') -if want_pam != 'false' and not ossfuzz +if want_pam != 'false' and not fuzzer_build libpam = cc.find_library('pam', required : want_pam == 'true') libpam_misc = cc.find_library('pam_misc', required : want_pam == 'true') have = libpam.found() and libpam_misc.found() @@ -898,7 +906,7 @@ conf.set10('HAVE_PAM', have) m4_defines += have ? ['-DHAVE_PAM'] : [] want_microhttpd = get_option('microhttpd') -if want_microhttpd != 'false' and not ossfuzz +if want_microhttpd != 'false' and not fuzzer_build libmicrohttpd = dependency('libmicrohttpd', version : '>= 0.9.33', required : want_microhttpd == 'true') @@ -911,7 +919,7 @@ conf.set10('HAVE_MICROHTTPD', have) m4_defines += have ? ['-DHAVE_MICROHTTPD'] : [] want_libcryptsetup = get_option('libcryptsetup') -if want_libcryptsetup != 'false' and not ossfuzz +if want_libcryptsetup != 'false' and not fuzzer_build libcryptsetup = dependency('libcryptsetup', version : '>= 1.6.0', required : want_libcryptsetup == 'true') @@ -923,7 +931,7 @@ endif conf.set10('HAVE_LIBCRYPTSETUP', have) want_libcurl = get_option('libcurl') -if want_libcurl != 'false' and not ossfuzz +if want_libcurl != 'false' and not fuzzer_build libcurl = dependency('libcurl', version : '>= 7.32.0', required : want_libcurl == 'true') @@ -941,7 +949,7 @@ if want_libidn == 'true' and want_libidn2 == 'true' error('libidn and libidn2 cannot be requested simultaneously') endif -if want_libidn != 'false' and want_libidn2 != 'true' and not ossfuzz +if want_libidn != 'false' and want_libidn2 != 'true' and not fuzzer_build libidn = dependency('libidn', required : want_libidn == 'true') have = libidn.found() @@ -951,7 +959,7 @@ else endif conf.set10('HAVE_LIBIDN', have) m4_defines += have ? ['-DHAVE_LIBIDN'] : [] -if not have and want_libidn2 != 'false' and not ossfuzz +if not have and want_libidn2 != 'false' and not fuzzer_build # libidn is used for both libidn and libidn2 objects libidn = dependency('libidn2', required : want_libidn2 == 'true') @@ -963,7 +971,7 @@ conf.set10('HAVE_LIBIDN2', have) m4_defines += have ? ['-DHAVE_LIBIDN2'] : [] want_libiptc = get_option('libiptc') -if want_libiptc != 'false' and not ossfuzz +if want_libiptc != 'false' and not fuzzer_build libiptc = dependency('libiptc', required : want_libiptc == 'true') have = libiptc.found() @@ -975,7 +983,7 @@ conf.set10('HAVE_LIBIPTC', have) m4_defines += have ? ['-DHAVE_LIBIPTC'] : [] want_qrencode = get_option('qrencode') -if want_qrencode != 'false' and not ossfuzz +if want_qrencode != 'false' and not fuzzer_build libqrencode = dependency('libqrencode', required : want_qrencode == 'true') have = libqrencode.found() @@ -986,7 +994,7 @@ endif conf.set10('HAVE_QRENCODE', have) want_gcrypt = get_option('gcrypt') -if want_gcrypt != 'false' and not ossfuzz +if want_gcrypt != 'false' and not fuzzer_build libgcrypt = cc.find_library('gcrypt', required : want_gcrypt == 'true') libgpg_error = cc.find_library('gpg-error', required : want_gcrypt == 'true') have = libgcrypt.found() and libgpg_error.found() @@ -1001,7 +1009,7 @@ endif conf.set10('HAVE_GCRYPT', have) want_gnutls = get_option('gnutls') -if want_gnutls != 'false' and not ossfuzz +if want_gnutls != 'false' and not fuzzer_build libgnutls = dependency('gnutls', version : '>= 3.1.4', required : want_gnutls == 'true') @@ -1013,7 +1021,7 @@ endif conf.set10('HAVE_GNUTLS', have) want_elfutils = get_option('elfutils') -if want_elfutils != 'false' and not ossfuzz +if want_elfutils != 'false' and not fuzzer_build libdw = dependency('libdw', required : want_elfutils == 'true') have = libdw.found() @@ -1024,7 +1032,7 @@ endif conf.set10('HAVE_ELFUTILS', have) want_zlib = get_option('zlib') -if want_zlib != 'false' and not ossfuzz +if want_zlib != 'false' and not fuzzer_build libz = dependency('zlib', required : want_zlib == 'true') have = libz.found() @@ -1035,7 +1043,7 @@ endif conf.set10('HAVE_ZLIB', have) want_bzip2 = get_option('bzip2') -if want_bzip2 != 'false' and not ossfuzz +if want_bzip2 != 'false' and not fuzzer_build libbzip2 = cc.find_library('bz2', required : want_bzip2 == 'true') have = libbzip2.found() @@ -1046,7 +1054,7 @@ endif conf.set10('HAVE_BZIP2', have) want_xz = get_option('xz') -if want_xz != 'false' and not ossfuzz +if want_xz != 'false' and not fuzzer_build libxz = dependency('liblzma', required : want_xz == 'true') have = libxz.found() @@ -1057,7 +1065,7 @@ endif conf.set10('HAVE_XZ', have) want_lz4 = get_option('lz4') -if want_lz4 != 'false' and not ossfuzz +if want_lz4 != 'false' and not fuzzer_build liblz4 = dependency('liblz4', required : want_lz4 == 'true') have = liblz4.found() @@ -1068,7 +1076,7 @@ endif conf.set10('HAVE_LZ4', have) want_xkbcommon = get_option('xkbcommon') -if want_xkbcommon != 'false' and not ossfuzz +if want_xkbcommon != 'false' and not fuzzer_build libxkbcommon = dependency('xkbcommon', version : '>= 0.3.0', required : want_xkbcommon == 'true') @@ -1080,7 +1088,7 @@ endif conf.set10('HAVE_XKBCOMMON', have) want_glib = get_option('glib') -if want_glib != 'false' and not ossfuzz +if want_glib != 'false' and not fuzzer_build libglib = dependency('glib-2.0', version : '>= 2.22.0', required : want_glib == 'true') @@ -1099,7 +1107,7 @@ endif conf.set10('HAVE_GLIB', have) want_dbus = get_option('dbus') -if want_dbus != 'false' and not ossfuzz +if want_dbus != 'false' and not fuzzer_build libdbus = dependency('dbus-1', version : '>= 1.3.2', required : want_dbus == 'true') @@ -1111,7 +1119,7 @@ endif conf.set10('HAVE_DBUS', have) default_dnssec = get_option('default-dnssec') -if ossfuzz +if fuzzer_build default_dnssec = 'no' endif if default_dnssec != 'no' and conf.get('HAVE_GCRYPT') == 0 @@ -2484,7 +2492,7 @@ foreach tuple : fuzzers defs = tuple.length() >= 4 ? tuple[3] : [] incs = tuple.length() >= 5 ? tuple[4] : includes - if ossfuzz + if fuzzer_build dependencies += fuzzing_engine else sources += 'src/fuzz/fuzz-main.c' diff --git a/meson_options.txt b/meson_options.txt index 9e7cad7471..eda5a579f2 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -294,3 +294,5 @@ option('install-tests', type : 'boolean', value : 'false', option('oss-fuzz', type : 'boolean', value : 'false', description : 'build against oss-fuzz') +option('llvm-fuzz', type : 'boolean', value : 'false', + description : 'build against LLVM libFuzzer') diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh index beb9d05b6f..8ae7625e1f 100755 --- a/scripts/oss-fuzz.sh +++ b/scripts/oss-fuzz.sh @@ -20,15 +20,27 @@ set -ex export LC_CTYPE=C.UTF-8 -if [ -z "$WORK" ]; then - echo '$WORK must be set' - exit 1 -fi +SANITIZER=${SANITIZER:-address -fsanitize-address-use-after-scope} +flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize-coverage=trace-pc-guard,trace-cmp" + +export CFLAGS=${CFLAGS:-$flags} +export CXXFLAGS=${CXXFLAGS:-$flags} +export CC=${CC:-clang} +export CXX=${CXX:-clang++} +export WORK=${WORK:-$(pwd)} +export OUT=${OUT:-$(pwd)/out} +mkdir -p $OUT + build=$WORK/build rm -rf $build mkdir -p $build -meson $build -Doss-fuzz=true -Db_lundef=false +fuzzflag="oss-fuzz=true" +if [ -z "$FUZZING_ENGINE" ]; then + fuzzflag="llvm-fuzz=true" +fi + +meson $build -D$fuzzflag -Db_lundef=false ninja -C $build fuzzers # get DNS packet corpus @@ -40,4 +52,4 @@ mkdir -p $OUT/src/shared mv $build/src/shared/libsystemd-shared-*.so $OUT/src/shared find $build -maxdepth 1 -type f -executable -name "fuzz-*" -exec mv {} $OUT \; -mv $build/*.so src/fuzz/*.options $OUT +cp src/fuzz/*.options $OUT