googleprojectzero / Jackalope

Binary, coverage-guided fuzzer for Windows, macOS, Linux and Android
Apache License 2.0
1.1k stars 128 forks source link

Fuzzer quits without saving crash #58

Open apx-1 opened 5 months ago

apx-1 commented 5 months ago

I had a similar issue like https://github.com/googleprojectzero/Jackalope/issues/23.

When crash is detected, it tries to reproduce the crash.

// save crashes and hangs immediately when they are detected
  if (result == CRASH) {
    string crash_desc = tc->instrumentation->GetCrashName();

    if (crash_reproduce_retries > 0) {
        if (TryReproduceCrash(tc, sample, init_timeout, timeout) == CRASH) {
            // get a hopefully better name
            crash_desc = tc->instrumentation->GetCrashName();
        } else {
            crash_desc = "flaky_" + crash_desc;
        }
    }

If it is !tc->sampleDelivery->DeliverSample(sample), the fuzzer quits without saving the crash.

RunResult Fuzzer::TryReproduceCrash(ThreadContext* tc, Sample* sample, uint32_t init_timeout, uint32_t timeout) {
  RunResult result;

  for (int i = 0; i < crash_reproduce_retries; i++) {
    total_execs++;

    if (!tc->sampleDelivery->DeliverSample(sample)) {
      WARN("Error delivering sample, retrying with a clean target");
      tc->instrumentation->CleanTarget();
      if (!tc->sampleDelivery->DeliverSample(sample)) {
        FATAL("Repeatedly failed to deliver sample");
      }
    }

    result = tc->instrumentation->RunWithCrashAnalysis(tc->target_argc, tc->target_argv, init_timeout, timeout);
    tc->instrumentation->ClearCoverage();

    if (result == CRASH) return result;
  }

  return result;
}

I think it is better to save the crash before FATAL("Repeatedly failed to deliver sample");

apx-1 commented 5 months ago

I've noticed multiple !tc->sampleDelivery->DeliverSample(sample) checks prior to the steps that lead to Fuzzer::TryReproduceCrash. I found several valid crashes without these checks, so it might be better to remove them from Fuzzer::TryReproduceCrash? The fuzzer often FATALs when using file delivery in ram.

ifratric commented 5 months ago

Sure, we can remove the FATAL when reproducing crashes, I just pushed https://github.com/googleprojectzero/Jackalope/commit/36d79fbb9deb2e68c1b523df2460110d5accd6fd However, after saving the crash, the fuzzer will likely still error out because it will be unable to save the next mutated sample. I would be more interested in the root cause, why writing the sample fails for these targets.