AFLplusplus / LibAFL

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

Wrong permission for `inmemory_ondisk` corpus leads to endless loop #2356

Closed Mech0n closed 4 months ago

Mech0n commented 4 months ago

Describe the bug

there is a bug when using the save_testcase. I getting stuck in the loop for a long time, and then ctr overflow.

To Reproduce I'm not sure the bug can be replicated stably. Steps to reproduce the behavior:

  1. use my fuzzer.
    
    use std::{path::PathBuf, ptr::addr_of_mut, time::Duration};

use libafl::{ corpus::{Corpus, OnDiskCorpus}, events::SimpleEventManager, feedbacks::{CrashFeedback, ListFeedback}, inputs::BytesInput, monitors::SimpleMonitor, mutators::{havoc_mutations, StdScheduledMutator}, observers::ListObserver, schedulers::RandScheduler, stages::StdMutationalStage, state::StdState, Fuzzer, StdFuzzer, };

[cfg(unix)]

use libafl_bolts::shmem::UnixShMemProvider; use libafl_bolts::{ ownedref::OwnedMutPtr, rands::StdRand, shmem::ShMemProvider, tuples::tuple_list, }; use libafl_tinyinst::executor::TinyInstExecutor; static mut COVERAGE: Vec = vec![];

[cfg(not(any(target_vendor = "apple", windows, target_os = "linux")))]

fn main() {}

[cfg(any(target_vendor = "apple", windows, target_os = "linux"))]

fn main() { // Tinyinst things

use libafl::{corpus::InMemoryCorpus, state::HasCorpus};
let tinyinst_args = vec!["-instrument_module".to_string(), "ImageIO".to_string(), "-patch_return_addresses".to_string()];
let asan_args = vec!["target_env".to_string(),
    // "DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib".to_string()];
    "DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib".to_string()];

// use file to pass testcases
let args = vec![
    "test_imageio".to_string(),
    "-f".to_string(),
    "@@".to_string(),
];

let coverage = unsafe { OwnedMutPtr::Ptr(addr_of_mut!(COVERAGE)) };
let observer = ListObserver::new("cov", coverage);
let mut feedback = ListFeedback::new(&observer);

// let mut shmem_provider = UnixShMemProvider::new().unwrap();

let mut objective = CrashFeedback::new();
let mut state = StdState::new(
    StdRand::new(),
    InMemoryCorpus::<BytesInput>::new(),
    OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
    &mut feedback,
    &mut objective,
)
.unwrap();
let scheduler = RandScheduler::new();
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

let monitor = SimpleMonitor::new(|x| println!("{x}"));

let mut mgr = SimpleEventManager::new(monitor);
let mut executor = unsafe {
    TinyInstExecutor::builder()
        .tinyinst_args(tinyinst_args)
        .tinyinst_args(asan_args)
        .program_args(args) // .use_shmem()
        .persistent("test_imageio".to_string(), "_fuzz".to_string(), 1, 10000)
        .timeout(Duration::new(5, 0)) // .shmem_provider(&mut shmem_provider)
        .coverage_ptr(addr_of_mut!(COVERAGE))
        .build(tuple_list!(observer))
        .unwrap()
};

state
    .load_initial_inputs(
        &mut fuzzer,
        &mut executor,
        &mut mgr,
        &[PathBuf::from("/path/to/seeds")],
    )
    .unwrap_or_else(|_| {
        panic!(
            "Failed to load initial corpus at {:?}",
            PathBuf::from("/path/to/seeds")
        )
    });
println!("We imported {} inputs from disk.", state.corpus().count());

let mutator = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer
    .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
    .expect("error in fuzzing loop");

}


**Expected behavior**

 the fuzzer have a cpu usage 100% and don't start a new target. and if you use lldb to run the fuzzer, will break at the loop.

frame #12: 0x0000000100008c60 tinyinst_simplelibafl::corpus::inmemory_ondisk::InMemoryOnDiskCorpus$LT$I$GT$::save _testcase::h6f8bf94d41c0fa9f(self=0x000000016fdfdc48, testcase=0x0000000154812d30, idx=(__0 = 0)) at inmemory_ondisk.r s:390:20 frame #13: 0x0000000100008780 tinyinst_simple_$LT$libafl..corpus..inmemory_ondisk..InMemoryOnDiskCorpus$LT$I$GT$$ u20$as$u20$libafl..corpus..Corpus$GT$::add::h3bae08c0e2f94843(self=0x000000016fdfdc48, testcase=) at inme mory_ondisk.rs:79:9 frame #14: 0x0000000100006d08 tinyinstsimple`$LT$libafl..corpus..cached..CachedOnDiskCorpus$LT$I$GT$$u20$as$u20$ libafl..corpus..Corpus$GT$::add::h736acc547877374f(self=0x000000016fdfdc48, testcase=) at cached.rs:94:9 frame #15: 0x0000000100019e9c tinyinstsimple`$LT$libafl..corpus..ondisk..OnDiskCorpus$LT$I$GT$$u20$as$u20$libafl ..corpus..Corpus$GT$::add::h1243d62103fa5185(self=0x000000016fdfdc48, testcase=) at ondisk.rs:94:9 frame #16: 0x0000000100004f84 tinyinstsimple`$LT$libafl..fuzzer..StdFuzzer$LT$CS$C$F$C$OF$C$OT$GT$$u20$as$u20$li bafl..fuzzer..ExecutionProcessor$LT$OT$GT$$GT$::process_execution::h161385f0d8e16bdb(self=0x000000016fdfe600, state=0x 000000016fdfdb80, manager=0x000000016fdfe6a0, input=BytesInput @ 0x000000016fdfc5a0, exec_res=0x000000016fdfc4ff, obse rvers=0x000000016fdfe700, exit_kind=0x000000016fdfc6de, send_events=true) at mod.rs:504:17 frame #17: 0x0000000100005450 tinyinstsimple`$LT$libafl..fuzzer..StdFuzzer$LT$CS$C$F$C$OF$C$OT$GT$$u20$as$u20$li bafl..fuzzer..ExecutionProcessor$LT$OT$GT$$GT$::execute_and_process::h79f098c69f260a89(self=0x000000016fdfe600, state= 0x000000016fdfdb80, manager=0x000000016fdfe6a0, input=BytesInput @ 0x000000016fdfc7b0, observers=0x000000016fdfe700, e xit_kind=0x000000016fdfc6de, send_events=true) at mod.rs:416:26 frame #18: 0x00000001000043b0 tinyinstsimple`$LT$libafl..fuzzer..StdFuzzer$LT$CS$C$F$C$OF$C$OT$GT$$u20$as$u20$li bafl..fuzzer..EvaluatorObservers$LT$OT$GT$$GT$::evaluate_input_with_observers::h51cbadfc653dcb28(self=0x000000016fdfe6 00, state=0x000000016fdfdb80, executor=0x000000016fdfe700, manager=0x000000016fdfe6a0, input=BytesInput @ 0x000000016f dfcc70, send_events=true) at mod.rs:550:9 frame #19: 0x00000001000031c8 tinyinstsimple`$LT$libafl..fuzzer..StdFuzzer$LT$CS$C$F$C$OF$C$OT$GT$$u20$as$u20$li bafl..fuzzer..Evaluator$LT$E$C$EM$GT$$GT$::evaluate_input_events::h5d54ff3a89b31f9d(self=0x000000016fdfe600, state=0x0 00000016fdfdb80, executor=0x000000016fdfe700, manager=0x000000016fdfe6a0, input=, send_events=true) at mo d.rs:574:9 frame #20: 0x00000001000059a8 tinyinst_simplelibafl::fuzzer::Evaluator::evaluate_input::h64073833a611a422(self=0x 000000016fdfe600, state=0x000000016fdfdb80, executor=0x000000016fdfe700, manager=0x000000016fdfe6a0, input=<unavailabl e>) at mod.rs:143:9 frame #21: 0x000000010003c574 tinyinst_simplelibafl::stages::mutational::MutationalStage::perform_mutational::h12 2a5f9eb94c6a61(self=0x000000016fdfecf0, fuzzer=0x000000016fdfe600, executor=0x000000016fdfe700, state=0x000000016fdfdb 80, manager=0x000000016fdfe6a0) at mutational.rs:139:35 frame #22: 0x000000010003bad4 tinyinstsimple`$LT$libafl..stages..mutational..StdMutationalStage$LT$E$C$EM$C$I$C$ M$C$Z$GT$$u20$as$u20$libafl..stages..Stage$LT$E$C$EM$C$Z$GT$$GT$::perform::hc1d3230782e0febe(self=0x000000016fdfecf0, fuzzer=0x000000016fdfe600, executor=0x000000016fdfe700, state=0x000000016fdfdb80, manager=0x000000016fdfe6a0) at mutat ional.rs:224:19 frame #23: 0x000000010003ca9c tinyinst_simplelibafl::stages::Stage::perform_restartable::hff8836715bc2e462(self=0 x000000016fdfecf0, fuzzer=0x000000016fdfe600, executor=0x000000016fdfe700, state=0x000000016fdfdb80, manager=0x0000000 16fdfe6a0) at mod.rs:118:13 frame #24: 0x000000010003be80 tinyinst_simple_$LT$$LP$Head$C$Tail$RP$$u20$as$u20$libafl..stages..StagesTuple$LT$E $C$EM$C$$LT$Head$u20$as$u20$libafl..state..UsesState$GT$..State$C$Z$GT$$GT$::perform_all::hdd9f7fc92a6cc3a7(self=0x000 000016fdfecf0, fuzzer=0x000000016fdfe600, executor=0x000000016fdfe700, state=0x000000016fdfdb80, manager=0x000000016fd fe6a0) at mod.rs:202:17 frame #25: 0x0000000100003ddc tinyinstsimple`$LT$libafl..fuzzer..StdFuzzer$LT$CS$C$F$C$OF$C$OT$GT$$u20$as$u20$li bafl..fuzzer..Fuzzer$LT$E$C$EM$C$ST$GT$$GT$::fuzz_one::h56d76884018ec231(self=0x000000016fdfe600, stages=0x000000016fd fecf0, executor=0x000000016fdfe700, state=0x000000016fdfdb80, manager=0x000000016fdfe6a0) at mod.rs:731:9 frame #26: 0x00000001000058d8 tinyinst_simplelibafl::fuzzer::Fuzzer::fuzz_loop::h588b38bf2b7c338b(self=0x00000001 6fdfe600, stages=0x000000016fdfecf0, executor=0x000000016fdfe700, state=0x000000016fdfdb80, manager=0x000000016fdfe6a0 ) at mod.rs:219:13 frame #27: 0x0000000100010140 tinyinst_simpletinyinst_simple::main::h95ff03309c547e4c at main.rs:94:5 frame #28: 0x000000010001ca3c tinyinst_simplecore::ops::function::FnOnce::call_once::hfe60308ca58b9518((null)=(ti nyinst_simpletinyinst_simple::main::h95ff03309c547e4c at main.rs:28), (null)=) at function.rs:250:5 frame #29: 0x0000000100009e14 tinyinst_simplestd::sys_common::backtrace::__rust_begin_short_backtrace::h4a247c582 479c49d(f=(tinyinst_simpletinyinst_simple::main::h95ff03309c547e4c at main.rs:28)) at backtrace.rs:155:18 frame #30: 0x00000001000494d8 tinyinst_simplestd::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hac6dc5f1b8db005b at rt.rs:166:18 frame #31: 0x0000000100341c1c tinyinst_simplestd::rt::lang_startinternal::h39923ab4c3913741 [inlined] core::ops: :function::impls::$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::heaba8a29e03240 69 at function.rs:284:13 [opt] frame #32: 0x0000000100341c14 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::panic king::try::do_call::h6e5fac4f4884d97b at panicking.rs:552:40 [opt] frame #33: 0x0000000100341c14 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::panic king::try::h2b98e2f3cf76cd78 at panicking.rs:516:19 [opt] frame #34: 0x0000000100341c14 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::panic ::catch_unwind::hba9c97319335c08b at panic.rs:146:14 [opt] frame #35: 0x0000000100341c14 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::rt::l ang_startinternal::$u7b$$u7b$closure$u7d$$u7d$::h18efdcfb68f002e8 at rt.rs:148:48 [opt] frame #36: 0x0000000100341c14 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::panic king::try::do_call::ha793e16770aada4d at panicking.rs:552:40 [opt] frame #37: 0x0000000100341c10 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::panic king::try::h8aa812e3e1310d12 at panicking.rs:516:19 [opt] frame #38: 0x0000000100341c10 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 [inlined] std::panic ::catch_unwind::h38c4879f2623185e at panic.rs:146:14 [opt] frame #39: 0x0000000100341c10 tinyinst_simplestd::rt::lang_start_internal::h39923ab4c3913741 at rt.rs:148:20 [opt ] frame #40: 0x00000001000494a4 tinyinst_simplestd::rt::lang_start::hea978e24bc60cea6(main=(tinyinst_simpletinyins t_simple::main::h95ff03309c547e4c at main.rs:28), argc=1, argv=0x000000016fdff2e0, sigpipe='\0') at rt.rs:165:17 frame #41: 0x00000001000102b0 tinyinst_simplemain + 36 frame #42: 0x00000001848920e0 dyldstart + 2360

domenukk commented 4 months ago

How many {filename}-{ctr} files do you have? I don't see why this could loop. Is the path possibly no longer available? That would be another explanation why .is_ok isn't ... ok.

https://github.com/AFLplusplus/LibAFL/blob/7c95afc42fd5e418a6efad3f39122bb915c0a10c/libafl/src/corpus/inmemory_ondisk.rs#L394

Mech0n commented 4 months ago

Sorry. Its my fault. I made a mistake about the ownership of the corpus. Thx!

domenukk commented 4 months ago

Well I guess we should catch this and report a proper error here, I'll reopen this for now :)

domenukk commented 4 months ago

Thank you for the report! :)