afl-cc: Don't offer __AFL_INIT() etc. in GCC/CLANG modes

instrumentation/README.persistent_mode.md documents in the section about
deferred forkserver initialization:

> With the location selected, add this code in the appropriate spot:
>
> ```c
> #ifdef __AFL_HAVE_MANUAL_CONTROL
>   __AFL_INIT();
> #endif
> ```
>
> You don't need the #ifdef guards, but including them ensures that the program
> will keep working normally when compiled with a tool other than afl-clang-fast/
> afl-clang-lto/afl-gcc-fast.
>
> Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
> (afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
> and you should be all set!


This strongly implies that you can compile a program that uses __AFL_INIT()
under an `#ifdef __AFL_HAVE_MANUAL_CONTROL` guard with afl-gcc/-clang.

However, this currently fails:

  $ cat example.c
  #include <stdio.h>

  int main(void) {
  #ifdef __AFL_HAVE_MANUAL_CONTROL
  	__AFL_INIT();
  #endif

  	puts("Hello");
  }
  $ afl-gcc example.c -o example
  afl-cc++4.06a by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: GCC-GCC
  [!] WARNING: You are using outdated instrumentation, install LLVM and/or gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast instead!
  afl-as++4.06a by Michal Zalewski
  [+] Instrumented 1 locations (64-bit, non-hardened mode, ratio 100%).
  /usr/bin/ld: /tmp/ccuJHcpt.o: in function `main':
  /home/jn/dev/fuzz/AFLplusplus/example.c:5: undefined reference to `__afl_manual_init'
  collect2: error: ld returned 1 exit status


The issue here is an inconsistency in afl-gcc (i.e. afl-cc operating in GCC mode):

 - afl-cc defines __AFL_HAVE_MANUAL_CONTROL and __AFL_INIT unconditionally
 - __AFL_INIT relies on __afl_manual_init, which is defined in afl-compiler-rt.o
 - afl-cc doesn't link afl-compiler-rt in GCC or CLANG mode


Since afl-gcc/-clang is documented as not supporting deferred forkserver
initialization, this patch omits the definitions of __AFL_HAVE_MANUAL_CONTROL
and related macros in GCC/CLANG mode.

This restores the ability to compile a deferred-forkserver program under
afl-gcc, if it can also be compiled under gcc.

[ In case someone reads this an feels adventurous enough (as I did) to
  think about enabling deferred forkserver under afl-gcc: Whether the
  deferred forkserver actually works can be verified by placing a
  usleep(100000) or similar at the start of main (before __AFL_INIT()),
  and watching the execution speed. It doesn't work. ]
This commit is contained in:
Jonathan Neuschäfer
2023-04-10 12:22:42 +02:00
parent 0911525194
commit 9e3e1a5512

View File

@ -1101,10 +1101,16 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; if (!have_c) cc_params[cc_par_cnt++] = "-lrt";
#endif #endif
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
/* As documented in instrumentation/README.persistent_mode.md, deferred
forkserver initialization and persistent mode are not available in afl-gcc
and afl-clang. */
if (compiler_mode != GCC && compiler_mode != CLANG) {
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
/* When the user tries to use persistent or deferred forkserver modes by /* When the user tries to use persistent or deferred forkserver modes by
appending a single line to the program, we want to reliably inject a appending a single line to the program, we want to reliably inject a
signature into the binary (to be picked up by afl-fuzz) and we want signature into the binary (to be picked up by afl-fuzz) and we want
@ -1133,6 +1139,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"unsigned char __afl_fuzz_alt[1048576];" "unsigned char __afl_fuzz_alt[1048576];"
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
}
if (plusplus_mode) { if (plusplus_mode) {
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
@ -1169,6 +1177,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff "
"? 0 : *__afl_fuzz_len)"; "? 0 : *__afl_fuzz_len)";
if (compiler_mode != GCC && compiler_mode != CLANG) {
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
"-D__AFL_LOOP(_A)=" "-D__AFL_LOOP(_A)="
"({ static volatile const char *_B __attribute__((used,unused)); " "({ static volatile const char *_B __attribute__((used,unused)); "
@ -1199,6 +1209,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
#endif /* ^__APPLE__ */ #endif /* ^__APPLE__ */
"_I(); } while (0)"; "_I(); } while (0)";
}
if (x_set) { if (x_set) {
cc_params[cc_par_cnt++] = "-x"; cc_params[cc_par_cnt++] = "-x";