AFL: segfault and lock resetting (fixes #497)#731
Conversation
ctk21
left a comment
There was a problem hiding this comment.
So using caml_fatal_error in caml_init_domains is a good thing.
I'm a bit worried about allowing fork in caml_setup_afl without checking that there are not multiple domains running, but I'm not an AFL expert. From what I could tell, caml_setup_afl is called from 'instrumented modules during intitialization'. Is it not possible for the following to happen:
- module A: uninstrumented and starts a domain
- module B: instrumented but initialized after module A at which point we have multiple domains
If this could happen, it could be fixed by inserting a caml_domain_alone() guard and erroring out if multiple domains are running?
This seems like a reasonable step to move forward. |
|
Following @ctk21's suggestion I've added a |
|
I noticed that This is caused by c0ef11f AFAICS which unified Thematically this is part of getting "AFL instrumentation working again" - but this can also be submitted as a separate PR if you prefer. |
Thanks, this seems correct to me, but I am not an expert of the affected code so it is best proof-read by someone else as well. |
kayceesrk
left a comment
There was a problem hiding this comment.
The changes look good to me.
…fix-fatal-unlock AFL: segfault and lock resetting (fixes ocaml#497). Also fixes broken ./configure -afl-instrument && make
…fix-fatal-unlock AFL: segfault and lock resetting (fixes ocaml#497). Also fixes broken ./configure -afl-instrument && make
This is a fix to get AFL-instrumentation running on multicore again.
First off, the segfault reported in #497 is caused by a NULL-pointer dereference during error reporting.
The error is triggered because
afl-fuzzruns the tested program under a memory budget withsetrlimit:https://github.com/google/AFL/blob/61037103ae3722c8060ff7082994836a794f978e/afl-fuzz.c#L2034-L2040
The allocation of the minor heap space in
caml_init_domainsthus fails and callscaml_raise_out_of_memory.It eventually ends up in
caml_raisewhere it dereferencesCaml_statewhich hasn't been initialized yet:ocaml-multicore/runtime/fail_nat.c
Line 74 in 13a6be2
The PR changes
caml_init_domainsto usecaml_fatal_errorconsistently.Secondly, the AFL-instrumentation uses
forkas an optimization to push more tests through.For a simple setup,
afl-fuzzcan fork and execute a program repeatedly for each mutated input.This is the behaviour you get with
AFL_NO_FORKSRV=1 afl-fuzz -i input -o output a.out(also mentioned in #497).To save time on redundant linking and initialization AFL also offers a "fork server" mode. This mode instead pauses the instrumented program at the point just before "proper execution" begins, and then cheaply forks test programs whenever
afl-fuzztells it to:ocaml-multicore/runtime/afl.c
Lines 116 to 120 in 13a6be2
This setup is described in more detail in https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
Note: Because we are still during initialization this
forkoccurrence will only execute with 1 domain running.The child however has problems with unlocking akin to #471. Since
afl-fuzzsilences the tested programhttps://github.com/google/AFL/blob/61037103ae3722c8060ff7082994836a794f978e/afl-fuzz.c#L2067-L2068
an
strace -fhelped reveal the problem:Because the child quickly fails silently during
afl-fuzzsperform_dry_runit reports it asNo instrumentation detectedwhich is a bit confusing https://github.com/google/AFL/blob/61037103ae3722c8060ff7082994836a794f978e/afl-fuzz.c#L2629-L2632To fix the unlock issue the PR uses the
caml_atfork_hookfrom 1a2c612With this fix the test case from #497 runs again using
-m none(no memory budget).I'll submit a separate PR regarding heap memory requirements.