Research impact of tb_flush after init_forkserver
Closed this issue · 3 comments
The current fork-server implementation on X64 might be negatively impacted by tb-flush
in cpu-exec of unicorn:
https://github.com/unicorn-engine/unicorn/blob/0551b56633f658ec760eac54c14712d712b746d7/qemu/cpu-exec.c#
Problem:
To start the fork-server, a single insn is executed.
Afterwards, we exit the cpu loop and translated blocks are flushed.
Since the parent will wait for translation requests at this first insn, all pre-jitted blocks on future children may simply be flushed and re-jitted after input from AFL is read.
Very unsuccessfully tried
index 94184a2..5f6e9d5 100755
--- a/qemu/cpu-exec.c
+++ b/qemu/cpu-exec.c
@@ -290,7 +299,13 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
// Unicorn: flush JIT cache to because emulation might stop in
// the middle of translation, thus generate incomplete code.
// TODO: optimize this for better performance
+#if defined(UNICORN_AFL)
+ if (!env->uc->afl_area_ptr) {
+ tb_flush(env);
+ }
+#else
tb_flush(env);
+#endif
-> The (normally working) testcase crashes with Invalid instruction (UC_ERR_INSN_INVALID) at address ffffffff83e00108
after the forkserver started.
Found the root cause:
- After
uc_emu_start
was called for the second time in the child, the parent is still stuck in the first call touc_emu_start
, waiting to translate new basic blocks. - The
until
address in the parent differs from theuntil
address of the child. - After the second fork, the child uses the cached translation block of the parent.
- As opposed to the first run in which the child translates the block itself, the second run will not stop at the correct
until
address (it would, instead, stop at the parent'suntil
address). - The child runs until it crashes somewhere (or loops forever)
As fix, I've started to add a uc_afl_forkserver_start
function that can take a list of exits, see https://github.com/domenukk/unicorn/blob/55a7cec601f380226ec1e170f325310e7720e48c/bindings/python/unicornafl/unicorn.py#L376
This will be upstreamed to AFL++, the trickle into this repo.