AFLplusplus / LibAFL

Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...
Other
1.99k stars 306 forks source link

Libfuzzer shim crash #2345

Closed anarcheuz closed 3 months ago

anarcheuz commented 3 months ago

commit: 50d75422c8b26089954d8d1b93560400dbeab14a

Describe the bug I was trying the libfuzzer shim on a C project:

thread '<unnamed>' panicked at .../LibAFL/libafl_targets/src/libfuzzer/mutators.rs:354:27:
source slice length (4031) does not match destination slice length (6169)
stack backtrace:
   0: rust_begin_unwind
             at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/panicking.rs:658:5
   1: core::panicking::panic_fmt
             at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/core/src/panicking.rs:74:14
   2: core::slice::<impl [T]>::copy_from_slice::len_mismatch_fail
             at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/core/src/slice/mod.rs:3639:13
   3: core::slice::<impl [T]>::copy_from_slice
             at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/core/src/slice/mod.rs:3646:13
   4: <libafl_targets::libfuzzer::mutators::LLVMCustomMutator<MT,SM,_> as libafl::mutators::scheduled::ScheduledMutator<libafl::inputs::bytes::BytesInput,MT,S>>::scheduled_mutate
             at ./LibAFL/libafl_targets/src/libfuzzer/mutators.rs:354:9
   5: <libafl_targets::libfuzzer::mutators::LLVMCustomMutator<MT,SM,_> as libafl::mutators::Mutator<libafl::inputs::bytes::BytesInput,S>>::mutate
             at ./LibAFL/libafl_targets/src/libfuzzer/mutators.rs:299:9
   6: libafl::stages::mutational::MutationalStage::perform_mutational
             at ./LibAFL/libafl/src/stages/mutational.rs:130:27
   7: <libafl::stages::mutational::StdMutationalStage<E,EM,I,M,Z> as libafl::stages::Stage<E,EM,Z>>::perform
             at ./LibAFL/libafl/src/stages/mutational.rs:231:19
   8: libafl::stages::Stage::perform_restartable
             at ./LibAFL/libafl/src/stages/mod.rs:124:13
   9: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:208:17
  10: <libafl::stages::logics::IfStage<CB,E,EM,ST,Z> as libafl::stages::Stage<E,EM,Z>>::perform
             at ./LibAFL/libafl/src/stages/logics.rs:131:13
  11: libafl::stages::Stage::perform_restartable
             at ./LibAFL/libafl/src/stages/mod.rs:124:13
  12: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:208:17
  13: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:215:9
  14: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:215:9
  15: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:215:9
  16: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:215:9
  17: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
             at ./LibAFL/libafl/src/stages/mod.rs:215:9
  18: <libafl::fuzzer::StdFuzzer<CS,F,OF,OT> as libafl::fuzzer::Fuzzer<E,EM,ST>>::fuzz_one
             at ./LibAFL/libafl/src/fuzzer/mod.rs:734:9
  19: libafl::fuzzer::Fuzzer::fuzz_loop
             at ./LibAFL/libafl/src/fuzzer/mod.rs:219:13
  20: afl_libfuzzer_runtime::fuzz::do_fuzz
             at ./LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/fuzz.rs:97:5
  21: afl_libfuzzer_runtime::fuzz::fuzz::{{closure}}
             at ./LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:496:13
  22: afl_libfuzzer_runtime::start_fuzzing_single
             at ./LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:541:5
  23: afl_libfuzzer_runtime::fuzz::fuzz::{{closure}}
             at ./LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/fuzz.rs:230:13
  24: afl_libfuzzer_runtime::fuzz::fuzz
             at ./LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:500:9
  25: LLVMFuzzerRunDriver
             at ./LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:641:32
  26: main
             at ./LibAFL/libafl_targets/src/libfuzzer.c:42:10
  27: __libc_start_main
             at /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16
  28: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
fatal runtime error: failed to initiate panic, error 5
[2024-06-28T00:33:42Z ERROR libafl::executors::hooks::unix::unix_signal_handler] Crashed with SIGABRT
[2024-06-28T00:33:42Z ERROR libafl::executors::hooks::unix::unix_signal_handler] Double crash

[2024-06-28T00:33:42Z ERROR libafl::executors::hooks::unix::unix_signal_handler] We crashed at addr 0x3e80006002e, but are not in the target... Bug in the fuzzer? Exiting.
[2024-06-28T00:33:42Z ERROR libafl::executors::hooks::unix::unix_signal_handler] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CRASH ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Received signal SIGABRT at 0x007fcbb50ed00b, fault address: 0x00000000000000
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ REGISTERS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    r8 : 0x00000000000000, r9 : 0x007fff41d26440, r10: 0x00000000000008, r11: 0x00000000000246, 
    r12: 0x007fff41d26808, r13: 0x00000000000000, r14: 0x007fcbb50a59c0, r15: 0x0055815ce493d0, 
    rdi: 0x00000000000002, rsi: 0x007fff41d26440, rbp: 0x007fff41d26690, rbx: 0x007fcbb50a59c0, 
    rdx: 0x00000000000000, rax: 0x00000000000000, rcx: 0x007fcbb50ed00b, rsp: 0x007fff41d26440, 
    rip: 0x007fcbb50ed00b, efl: 0x00000000000246, 
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
       0: libafl_bolts::minibsod::generate_minibsod
                 at ..../LibAFL/libafl_bolts/src/minibsod.rs:1080:30
       1: libafl::executors::hooks::unix::unix_signal_handler::inproc_crash_handler
                 at ..../LibAFL/libafl/src/executors/hooks/unix.rs:248:36
       2: libafl::executors::hooks::unix::unix_signal_handler::<impl libafl_bolts::os::unix_signals::Handler for libafl::executors::hooks::inprocess::InProcessExecutorHandlerData>::handle
       3: libafl_bolts::os::unix_signals::handle_signal
                 at ..../LibAFL/libafl_bolts/src/os/unix_signals.rs:436:5
       4: <unknown>
       5: __libc_signal_restore_set
                 at /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/internal-signals.h:86:3
          __GI_raise
                 at /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:48:3
       6: __GI_abort
                 at /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:79:7
       7: std::sys::pal::unix::abort_internal
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/sys/pal/unix/mod.rs:366:14
       8: rust_panic
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/rt.rs:43:13
       9: std::panicking::rust_panic_with_hook
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/panicking.rs:818:5
      10: std::panicking::begin_panic_handler::{{closure}}
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/panicking.rs:667:13
      11: std::sys::backtrace::__rust_end_short_backtrace
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/sys/backtrace.rs:171:18
      12: rust_begin_unwind
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/std/src/panicking.rs:658:5
      13: core::panicking::panic_fmt
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/core/src/panicking.rs:74:14
      14: core::slice::<impl [T]>::copy_from_slice::len_mismatch_fail
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/core/src/slice/mod.rs:3639:13
      15: core::slice::<impl [T]>::copy_from_slice
                 at /rustc/d7f6ebacee13b6c03623c4b74197280454ede8de/library/core/src/slice/mod.rs:3646:13
          <libafl_targets::libfuzzer::mutators::LLVMCustomMutator<MT,SM,_> as libafl::mutators::scheduled::ScheduledMutator<libafl::inputs::bytes::BytesInput,MT,S>>::scheduled_mutate
                 at .../LibAFL/libafl_targets/src/libfuzzer/mutators.rs:354:9
          <libafl_targets::libfuzzer::mutators::LLVMCustomMutator<MT,SM,_> as libafl::mutators::Mutator<libafl::inputs::bytes::BytesInput,S>>::mutate
                 at .../LibAFL/libafl_targets/src/libfuzzer/mutators.rs:299:9
      16: libafl::stages::mutational::MutationalStage::perform_mutational
                 at .../LibAFL/libafl/src/stages/mutational.rs:130:27
          <libafl::stages::mutational::StdMutationalStage<E,EM,I,M,Z> as libafl::stages::Stage<E,EM,Z>>::perform
                 at .../LibAFL/libafl/src/stages/mutational.rs:231:19
          libafl::stages::Stage::perform_restartable
                 at .../LibAFL/libafl/src/stages/mod.rs:124:13
      17: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:208:17
          <libafl::stages::logics::IfStage<CB,E,EM,ST,Z> as libafl::stages::Stage<E,EM,Z>>::perform
                 at .../LibAFL/libafl/src/stages/logics.rs:131:13
          libafl::stages::Stage::perform_restartable
                 at .../LibAFL/libafl/src/stages/mod.rs:124:13
      18: <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:208:17
          <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:215:9
          <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:215:9
          <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:215:9
          <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:215:9
          <(Head,Tail) as libafl::stages::StagesTuple<E,EM,<Head as libafl::state::UsesState>::State,Z>>::perform_all
                 at .../LibAFL/libafl/src/stages/mod.rs:215:9
          <libafl::fuzzer::StdFuzzer<CS,F,OF,OT> as libafl::fuzzer::Fuzzer<E,EM,ST>>::fuzz_one
                 at .../LibAFL/libafl/src/fuzzer/mod.rs:734:9
          libafl::fuzzer::Fuzzer::fuzz_loop
                 at .../LibAFL/libafl/src/fuzzer/mod.rs:219:13
          afl_libfuzzer_runtime::fuzz::do_fuzz
                 at .../LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/fuzz.rs:97:5
          afl_libfuzzer_runtime::fuzz::fuzz::{{closure}}
                 at .../LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:496:13
      19: afl_libfuzzer_runtime::start_fuzzing_single
                 at .../LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:541:5
          afl_libfuzzer_runtime::fuzz::fuzz::{{closure}}
                 at .../LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/fuzz.rs:230:13
          afl_libfuzzer_runtime::fuzz::fuzz
                 at .../LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:500:9
      20: LLVMFuzzerRunDriver
                 at .../LibAFL/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs:641:32
      21: main
                 at .../LibAFL/libafl_targets/src/libfuzzer.c:42:10
      22: __libc_start_main
                 at /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16
      23: _start

Looking at the file in question:

    fn scheduled_mutate(
        &mut self,
        state: &mut S,
        input: &mut S::Input,
    ) -> Result<MutationResult, Error> {
        let seed = state.rand_mut().next();
        let target = input.bytes();
        let mut bytes = Vec::with_capacity(state.max_size());
        bytes.extend_from_slice(target.as_slice());
        bytes.resize(state.max_size(), 0);

        // we assume that the fuzzer did not use this mutator, but instead utilised their own
        let result = Rc::new(RefCell::new(Ok(MutationResult::Mutated)));
        let proxy = MutatorProxy::new(state, &self.mutator, &result);
        let old = MUTATOR.with(|mutator| {
            let mut mutator = mutator.borrow_mut();
            mutator.replace(Box::new(proxy.weak()))
        });
        let new_size = unsafe {
            libafl_targets_libfuzzer_custom_mutator(
                bytes.as_mut_ptr(),
                target.as_slice().len(),
                bytes.len(),
                seed as u32,
            )
        };
        drop(proxy);
        MUTATOR.with(|mutator| {
            let mut mutator = mutator.borrow_mut();
            *mutator = old;
        });
        if result.deref().borrow().is_err() {
            return result.replace(Ok(MutationResult::Skipped));
        }
        bytes.truncate(new_size);
        input.bytes_mut().copy_from_slice(&bytes); //[1]
        Ok(MutationResult::Mutated)
    }
}

bytes cannot be the same size as input as it was truncated by new_size returned by libfuzzer's custom mutator. copy_from_slice will panic if they don't have the same size.

Please note the other scheduled_mutate() function that calls libafl_targets_libfuzzer_custom_crossover also has this issue.

domenukk commented 3 months ago

Your new_size should never exceed the size_t MaxSize parameter, and it looks like it does in this case?

domenukk commented 3 months ago

Ah wait, you are right. https://github.com/AFLplusplus/LibAFL/blob/50d75422c8b26089954d8d1b93560400dbeab14a/libafl_targets/src/libfuzzer/mutators.rs#L354

Want to do a PR?

domenukk commented 3 months ago

Actually, we might want a replace_bytes in BytesInput so we don't need the extra copy at all

domenukk commented 3 months ago

Actually it should be doable in place

domenukk commented 3 months ago

Can you try #2347? Thanks for reporting! We could also use some CI for this...

anarcheuz commented 3 months ago

Seems to be fixed. Thank you!

domenukk commented 3 months ago

Thanks for reporting