Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVMFuzzerRunDriver() support #1515

Closed
lszekeres opened this issue Sep 12, 2022 · 8 comments
Closed

LLVMFuzzerRunDriver() support #1515

lszekeres opened this issue Sep 12, 2022 · 8 comments

Comments

@lszekeres
Copy link
Contributor

lszekeres commented Sep 12, 2022

Please support the LLVMFuzzerRunDriver interface to enable fuzzing targets that must provide their own main().

Supporting this should be simple, i.e., by putting something like:

int main() { return LLVMFuzzerRunDriver(); } 

in a separate compilation unit (see e.g., libfuzzer) and allow linking without it. So the fuzz target's main can run first, which can call the engine's "main", i.e., LLVMFuzzerRunDriver().

cc: @domenukk

@vanhauser-thc
Copy link
Member

can you please give some more information what is needed?
does the fuzzing targets call LLVMFuzzerRunDriver and this starts libfuzzer by setting everything up and then calling LLVMFuzzerTestOneInput? So we would need to implement LLVMFuzzerRunDriver ourself?
Or something else needed?
Can you link an example target?
I am currently on vacation and would have all the information I need to implement this when I am back.

@domenukk
Copy link
Member

LLVMFuzzerRunDriver starts the fuzzing loop.
I've done that in the past for LibAFL:
https://github.com/AFLplusplus/LibAFL/blob/2504b6dae3584f12b7ed1309919d6a5611278545/fuzzers/libafl_atheris/src/lib.rs#L107

So yes we need to implement the driver, that then calls out to the fuzzer.
I guess we can always add LLVMFuzzerRunDriver, but we still don't know if we need our own main or not (should we do weak linking, or a new flag?)

@lszekeres
Copy link
Contributor Author

Can you link an example target?

Here's an example how it works with libFuzzer:

#include <iostream>

extern "C" int LLVMFuzzerRunDriver(int *argc, char ***argv,
                                   int (*callback)(const uint8_t *data, size_t size));

int MyFuzzTarget(const uint8_t *data, size_t size) {
  std::cout << "Fuzz me!\n";
  return 0;
}

int main(int argc, char *argv[]) {
  std::cout << "I must run before fuzzing! ";
  std::cout << "Can't do LLVMFuzzerInitialize, sorry.\n";
  LLVMFuzzerRunDriver(&argc, &argv, &MyFuzzTarget);
}
$ clang++ -o main -fsanitize=fuzzer-no-link main.cc /usr/lib/llvm-14/lib/clang/14.0.6/lib/linux/libclang_rt.fuzzer_no_main-x86_64.a
$ ./main
I must run before fuzzing! Can't do LLVMFuzzerInitialize, sorry.
INFO: Seed: 1997674024
INFO: Loaded 1 modules   (4 inline 8-bit counters): 4 [0x55c857c99fc3, 0x55c857c99fc7), 
INFO: Loaded 1 PC tables (4 PCs): 4 [0x55c857c99fc8,0x55c857c9a008), 
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
Fuzz me!
INFO: A corpus is not provided, starting from an empty corpus
Fuzz me!
#2	INITED cov: 1 ft: 1 corp: 1/1b exec/s: 0 rss: 29Mb
...

I guess we can always add LLVMFuzzerRunDriver, but we still don't know if we need our own main or not (should we do weak linking, or a new flag?)

libFuzzer provides an additional no_main version of its runtime:

$ find $(llvm-config --libdir) -name "libclang_rt.fuzzer*-x86_64.a"
/usr/lib/llvm-14/lib/clang/14.0.6/lib/linux/libclang_rt.fuzzer_interceptors-x86_64.a
/usr/lib/llvm-14/lib/clang/14.0.6/lib/linux/libclang_rt.fuzzer_no_main-x86_64.a
/usr/lib/llvm-14/lib/clang/14.0.6/lib/linux/libclang_rt.fuzzer-x86_64.a

@vanhauser-thc
Copy link
Member

@lszekeres can you have a look - or better test - if b7a2c7e is already all that is needed?

@vanhauser-thc
Copy link
Member

plus 636025d

@domenukk
Copy link
Member

That's a nice solution! I wonder if there's any potential price for the indirect call here, alternatively we could add a function that both, main and the runner, call and then main can call directly though to LLVMTestOneInput, the runner calls the callback

@lszekeres
Copy link
Contributor Author

@lszekeres can you have a look - or better test - if b7a2c7e is already all that is needed?

thanks! if we fix the rest of the calls too, it's doing something :)

@vanhauser-thc
Copy link
Member

I wrote that in the hotel lobby after a night were our flight had to return to the airport due hydraulic problems ... ;)
thanks for the fixing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants