mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.4k stars 1.55k forks source link

Missing support for CFLAGS="-fsanitize=fuzzer"? #7761

Open lmcjoma opened 3 years ago

lmcjoma commented 3 years ago

I am trying to build a system with meson where fuzzing is activated. The code I am trying to build is here: https://gitlab.freedesktop.org/elmarco/libslirp/-/commit/9fba8af484ec6bc10b22e3f49d9e34d95c28b086

However, when I try to build it according to the second method in the commit log I get the following:

FLAGS="-fsanitize=fuzzer" CC=clang CXX=clang++ meson build-clang -Db_lundef=false The Meson build system Version: 0.55.3 Source dir: /home/jmaloy/fuzzing/lureau/libslirp Build dir: /home/jmaloy/fuzzing/lureau/libslirp/build-clang Build type: native build Project name: slirp Project version: 4.0.0 Using 'CC' from environment with value: 'clang' Using 'CFLAGS' from environment with value: '-fsanitize=fuzzer'

meson.build:1:0: ERROR: Compiler clang can not compile programs.

A full log file can be found at /home/jmaloy/fuzzing/lureau/libslirp/build-clang/meson-logs/meson-log.txt [jmaloy@f31 libslirp]$

The log referred to above looks as follows:

Build started at 2020-09-19T15:11:11.217041 Main binary: /usr/bin/python3 Build Options: -Db_lundef=false Python system: Linux The Meson build system Version: 0.55.3 Source dir: /home/jmaloy/fuzzing/lureau/libslirp Build dir: /home/jmaloy/fuzzing/lureau/libslirp/build-clang Build type: native build None of 'PKG_CONFIG_PATH' are defined in the environment, not changing global flags. None of 'PKG_CONFIG_PATH' are defined in the environment, not changing global flags. Project name: slirp Project version: 4.0.0 Using 'CC' from environment with value: 'clang' Using 'CFLAGS' from environment with value: '-fsanitize=fuzzer' None of 'LDFLAGS' are defined in the environment, not changing global flags. None of 'CPPFLAGS' are defined in the environment, not changing global flags. None of 'CC_LD' are defined in the environment, not changing global flags. Sanity testing C compiler: clang Is cross compiler: False. None of 'CC_LD' are defined in the environment, not changing global flags. Sanity check compiler command line: clang /home/jmaloy/fuzzing/lureau/libslirp/build-clang/meson-private/sanitycheckc.c -o /home/jmaloy/fuzzing/lureau/libslirp/build-clang/meson-private/sanitycheckc.exe -fsanitize=fuzzer -pipe -D_FILE_OFFSET_BITS=64 Sanity check compile stdout:

Sanity check compile stderr: /usr/bin/ld: /tmp/sanitycheckc-2fd9d1.o: in function main': sanitycheckc.c:(.text.main[main]+0x0): multiple definition ofmain'; /usr/lib64/clang/9.0.1/lib/linux/libclang_rt.fuzzer-x86_64.a(FuzzerMain.cpp.o):(.text.startup[.text.startup.group]+0x0): first defined here /usr/bin/ld: /usr/lib64/clang/9.0.1/lib/linux/libclang_rt.fuzzer-x86_64.a(FuzzerMain.cpp.o): in function main': (.text.startup[.text.startup.group]+0xf): undefined reference toLLVMFuzzerTestOneInput' clang-9: error: linker command failed with exit code 1 (use -v to see invocation)

meson.build:1:0: ERROR: Compiler clang can not compile programs.

My environment looks as follows:

$ uname -a Linux f31 5.7.15-100.fc31.x86_64 #1 SMP Tue Aug 11 17:18:01 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux (I.e., Fedora31) [jmaloy@f31 libslirp]$ clang --version clang version 9.0.1 (Fedora 9.0.1-2.fc31) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/bin [jmaloy@f31 libslirp]$ meson --version 0.55.3 [jmaloy@f31 libslirp]$ python --version Python 3.7.8 [jmaloy@f31 libslirp]$ ninja --version 1.9.0

I contacted the author of the program, but despite the commit log message he cannot remember he even tried this option, so I suspect this never worked for him either.

BR Jon Maloy jmaloy@redhat.com

stefanha commented 3 years ago

The meson.build file you linked manually links libfuzzer into the final executable, so CFLAGS="-fsanitize=fuzzer-no-link" may solve the issue: https://www.llvm.org/docs/LibFuzzer.html#fuzzer-usage

lmcjoma commented 3 years ago

Now it builds, just as it does when I don't use the flag at all.

But this doesn't bring me further unfortunately:

CFLAGS="-fsanitize=fuzzer-no-link" CC=clang CXX=clang++ meson build-clang -Db_lundef=false The Meson build system Version: 0.55.3 Source dir: /home/jmaloy/fuzzing/lureau/libslirp Build dir: /home/jmaloy/fuzzing/lureau/libslirp/build-clang Build type: native build Project name: slirp Project version: 4.0.0 Using 'CC' from environment with value: 'clang' Using 'CFLAGS' from environment with value: '-fsanitize=fuzzer-no-link' Using 'CC' from environment with value: 'clang' Using 'CFLAGS' from environment with value: '-fsanitize=fuzzer-no-link' C compiler for the host machine: clang (clang 9.0.0 "clang version 9.0.0 (https://github.com/llvm-mirror/llvm c62b24f070c9a4bb1a76409e623042a740cac4cd)") C linker for the host machine: clang ld.bfd 2.32-31 Host machine cpu family: x86_64 Host machine cpu: x86_64 Found pkg-config: /usr/bin/pkg-config (1.6.3) Run-time dependency glib-2.0 found: YES 2.62.6 Using 'CXX' from environment with value: 'clang++' Using 'CXX' from environment with value: 'clang++' C++ compiler for the host machine: clang++ (clang 9.0.0 "clang version 9.0.0 (https://github.com/llvm-mirror/llvm c62b24f070c9a4bb1a76409e623042a740cac4cd)") C++ linker for the host machine: clang++ ld.bfd 2.32-31 Configuring libslirp-version.h using configuration Checking if "fuzzer driver check" links: YES Build targets in project: 2 Found ninja-1.9.0 at /usr/bin/ninja

[jmaloy@f31 libslirp]$ cd build-clang/ [jmaloy@f31 build-clang]$ meson compile Found runner: ['/usr/bin/ninja'] ninja: Entering directory `.'

[1/36] Compiling C object libslirp.so.0.0.0.p/src_ip6_output.c.o [...] [33/36] Compiling C object fuzzing/fuzz-input.p/fuzz-input.c.o [34/36] Linking target libslirp.so.0.0.0 [36/36] Linking target fuzzing/fuzz-input

[jmaloy@f31 build-clang]$ ./fuzzing/fuzz-input ../fuzzing/IN/ ../fuzzing/IN/nc-10.0.2.2-8080.pcap... ../fuzzing/IN/nc-ident.pcap... ../fuzzing/IN/qemu.pkt... ../fuzzing/IN/tftp-get-blah.pkt... [jmaloy@f31 build-clang]$ ./fuzzing/fuzz-input ../fuzzing/IN/

///jon

stefanha commented 3 years ago

Based on the meson.build file in the commit you linked, you could try: ... meson -Dllvm-fuzz=true ...

That will link libfuzzer into the fuzz-input binary.

lmcjoma commented 3 years ago

Better, but: fuzzing/meson.build:5:2: ERROR: C++ shared or static library 'Fuzzer' not found

In my Makefile version I built libFuzzer myself and linked to it, but that cannot possibly be the intention. As I understand libfuzzer is a native part of clang?

stefanha commented 3 years ago

Maybe those meson.build files were written with a manually compiled libFuzzer in mind.

It may be easier to modify them to add "-fsanitize=fuzzer" on the fuzz-input executable() in meson.build. Then you don't need to use llvm-fuzz=true and it will use clang's version of libfuzzer.

Something like this:

executable(
  'fuzz-input', [extra_sources, 'fuzz-input.c'],
  dependencies : deps,
  c_args : '-fsanitize=fuzzer',
  link_args : '-fsanitize=fuzzer',
)

But I don't know the intention of the original meson.build files, they seem to have Google OSS-Fuzz support so maybe they expect an environment where libfuzzer has been provided...

lmcjoma commented 3 years ago

Yes, that, plus that I commented out main() in fuzz_main.c, solved it. And I need to spend more time on understanding meson... Thank you, Stefan!

elmarco commented 3 years ago

It seems to me meson recently (<1y) changed the way CFLAGS are checked. Now with CFLAGS="-fsanitize=fuzzer" it will fail to link during configure step. So CFLAGS="-fsanitize=fuzzer-no-link" seems necessary. And in theory, LDFLAGS="-fsanitize=fuzzer" should help too, but LDFLAGS seems not working (anymore?). So Stefan solution is good to me.

In general, I think we should avoid using environment variables anyway, and instead have meson.build handle adding/removing the flags (this may be annoying for things like OSSFuzz though) . And it would be nice if meson gained b_sanitize=fuzzer. (sadly, the combination of ASAN options there isn't very good either)

dcbaker commented 3 years ago

Really we should just extend the b_sanitize option to handle fuzzer correctly. Hand rolling this stuff is hard and easy to break, which is why we have the built-in option