Skip to content

Conversation

@neuschaefer
Copy link
Contributor

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

With the location selected, add this code in the appropriate spot:

#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. ]

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. ]
@vanhauser-thc
Copy link
Member

looks good thank you

@vanhauser-thc vanhauser-thc merged commit a5a122a into AFLplusplus:dev Apr 10, 2023
@neuschaefer neuschaefer deleted the nodefer branch April 10, 2023 16:55
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

Successfully merging this pull request may close these issues.

2 participants