diff --git a/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs b/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs index 48eac07ef9..af43c4bd3b 100644 --- a/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs +++ b/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs @@ -18,9 +18,11 @@ use std::{ use libafl::{ bolts::{ current_nanos, current_time, - os::dup2, + os::{dup2,Cores}, rands::StdRand, tuples::{tuple_list, Merge}, + shmem::{ShMemProvider,StdShMemProvider}, + launcher::Launcher, }, corpus::{ Corpus, OnDiskCorpus, PowerQueueCorpusScheduler, @@ -30,7 +32,7 @@ use libafl::{ feedbacks::{MapFeedbackState, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, - monitors::SimpleMonitor, + monitors::{MultiMonitor,SimpleMonitor}, mutators::{ scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, StdScheduledMutator, Tokens, @@ -42,7 +44,8 @@ use libafl::{ ShadowTracingStage, StdMutationalStage, }, state::{HasCorpus, HasMetadata, StdState}, - events::SimpleEventManager, + events::{SimpleEventManager,EventConfig}, + generators::RandBytesGenerator, Error, }; use libafl_qemu::{ @@ -61,7 +64,7 @@ use libafl_qemu::{ clock::ClockFeedback, clock::QemuClockIncreaseFeedback }; -use wcet_qemu_sys::worst::{HitFeedback,HitcountsMapObserver,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler}; +use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitcountsMapObserver,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler}; /// The fuzzer main @@ -214,7 +217,27 @@ fn fuzz( ) -> Result<(), Error> { env::remove_var("LD_LIBRARY_PATH"); - //=========== Initialize the Emulator + //=========== Analyze the binary to find the target function address + let mut elf_buffer = Vec::new(); + let elf = EasyElf::from_file(&kernel, &mut elf_buffer)?; + + let input_addr = elf + .resolve_symbol("FUZZ_INPUT", 0) + .expect("Symbol FUZZ_INPUT not found"); + let input_addr = virt2phys(input_addr,&elf.goblin()); + println!("FUZZ_INPUT @ {:#x}", input_addr); + let test_length_ptr = elf + .resolve_symbol("FUZZ_LENGTH", 0) + .expect("Symbol FUZZ_LENGTH not found"); + let test_length_ptr = virt2phys(test_length_ptr,&elf.goblin()); + println!("FUZZ_LENGTH @ {:#x}", test_length_ptr); + let check_breakpoint = elf + .resolve_symbol("trigger_Qemu_break", 0) + .expect("Symbol trigger_Qemu_break not found"); + let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin()); + println!("Breakpoint at {:#x}", check_breakpoint); + + //=========== Prepare Emulator Args let args: Vec = vec![ "qemu-system-arm", "-machine","mps2-an385", @@ -228,36 +251,8 @@ fn fuzz( "-S" ].iter().map(|x| x.to_string()).collect(); let env: Vec<(String, String)> = env::vars().collect(); - let emu = Emulator::new(&args, &env); - - //=========== Analyze the binary to find the target function address - let mut elf_buffer = Vec::new(); - let bin_path=kernel; - let elf = EasyElf::from_file(bin_path, &mut elf_buffer)?; - - let test_one_input_ptr = elf - .resolve_symbol("FUZZ_INPUT", 0) - .expect("Symbol FUZZ_INPUT not found"); - let test_one_input_ptr = virt2phys(test_one_input_ptr,&elf.goblin()); - println!("FUZZ_INPUT @ {:#x}", test_one_input_ptr); - let test_length_ptr = elf - .resolve_symbol("FUZZ_LENGTH", 0) - .expect("Symbol FUZZ_LENGTH not found"); - let test_length_ptr = virt2phys(test_length_ptr,&elf.goblin()); - println!("FUZZ_LENGTH @ {:#x}", test_length_ptr); - let check_breakpoint = elf - .resolve_symbol("trigger_Qemu_break", 0) - .expect("Symbol trigger_Qemu_break not found"); - let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin()); - println!("Breakpoint at {:#x}", check_breakpoint); - //====== Note the input field - let input_addr = test_one_input_ptr; - println!("Placing input at {:#x}", input_addr); - emu.set_breakpoint(check_breakpoint); // trigger_Qemu_break - - //====== Setup log and stdout let log = RefCell::new( OpenOptions::new() .append(true) @@ -265,30 +260,18 @@ fn fuzz( .open(&logfile)?, ); - #[cfg(unix)] - let mut stdout_cpy = unsafe { - let new_fd = dup(io::stdout().as_raw_fd())?; - File::from_raw_fd(new_fd) - }; - #[cfg(unix)] - let file_null = File::open("/dev/null")?; - - //====== Create the most simple status display and managers. - - // 'While the stats are state, they are usually used in the broker - which is likely never restarted - let monitor = SimpleMonitor::new(|s| { - #[cfg(unix)] - writeln!(&mut stdout_cpy, "{}", s).unwrap(); - #[cfg(windows)] - println!("{}", s); - writeln!(log.borrow_mut(), "{:?} {}", current_time(), s).unwrap(); + let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory"); + let monitor = MultiMonitor::new(|s| { + println!("{}",s); + writeln!(log.borrow_mut(), "{}",s).unwrap(); }); - // let mut shmem_provider = StdShMemProvider::new()?; - - //====== Create the most simple status display and managers. - let mut mgr = SimpleEventManager::new(monitor); + //====== Child Function + let mut run_client = |state: Option>, mut mgr, _core_id| { + //====== Set up Emu and termination-point + let emu = Emulator::new(&args, &env); + emu.set_breakpoint(check_breakpoint); // trigger_Qemu_break // Create an observation channel using the coverage map let edges = unsafe { &mut edges::EDGES_MAP }; let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM }; @@ -316,37 +299,32 @@ fn fuzz( }, }; let feedback = feedback_or!( + // New maximization map feedback linked to the edges observer and the feedback state MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false), - HitImprovingFeedback::new(target_map.clone()), + // HitImprovingFeedback::new(target_map.clone()), QemuClockIncreaseFeedback::default(), ClockFeedback::new_with_observer(&clock_observer) ); - // let feedback = feedback_or!( - // // New maximization map feedback linked to the edges observer and the feedback state - // MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false), - // MapHitIncreaseFeedback::new(), - // // Time feedback, this one does not need a feedback state - // TimeFeedback::new_with_observer(&time_observer) - // ); // A feedback to choose if an input is a solution or not - let objective = HitFeedback::new(target_map,0.0); + // let objective = HitFeedback::new(target_map,0.0); + let objective = SortedFeedback::new(); // create a State from scratch - let mut state = { + let mut state = state.unwrap_or_else(||{ StdState::new( // RNG StdRand::with_seed(current_nanos()), - // Corpus that will be evolved, we keep it in memory for performance - OnDiskCorpus::new(corpus_dir).unwrap(), + // Corpus that will be evolved + OnDiskCorpus::new(&corpus_dir).unwrap(), // Corpus in which we store solutions (crashes in this example), // on disk so the user can get them after stopping the fuzzer - OnDiskCorpus::new(objective_dir).unwrap(), + OnDiskCorpus::new(&objective_dir).unwrap(), // States of the feedbacks. // They are the data related to the feedbacks that you want to persist in the State. tuple_list!(feedback_state,clock::MaxIcountMetadata::default()), ) - }; + }); let calibration = CalibrationStage::new(&mut state, &edges_observer); @@ -407,20 +385,27 @@ fn fuzz( let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); // Read tokens - if let Some(tokenfile) = tokenfile { + if let Some(tokenfile) = &tokenfile { if state.metadata().get::().is_none() { - state.add_metadata(Tokens::from_tokens_file(tokenfile)?); + state.add_metadata(Tokens::from_tokens_file(&tokenfile)?); } } if state.corpus().count() < 1 { - state - .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()]) - .unwrap_or_else(|_| { - println!("Failed to load initial corpus at {:?}", &seed_dir); - process::exit(0); - }); - println!("We imported {} inputs from disk.", state.corpus().count()); + if _core_id == 0 && state.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()]).is_ok() { + // println!("We imported {} inputs from disk.", state.corpus().count()); + } else { + let mut generator = RandBytesGenerator::new(32); + state + .generate_initial_inputs( + &mut fuzzer, + &mut executor, + &mut generator, + &mut mgr, + 8, + ) + .expect("Failed to generate the initial corpus"); + } } let tracing = ShadowTracingStage::new(&mut executor); @@ -430,18 +415,13 @@ fn fuzz( // Remove target ouput (logs still survive) #[cfg(unix)] + let file_null = File::open("/dev/null")?; + #[cfg(unix)] { let null_fd = file_null.as_raw_fd(); dup2(null_fd, io::stdout().as_raw_fd())?; dup2(null_fd, io::stderr().as_raw_fd())?; } - // reopen file to make sure we're at the end - log.replace( - OpenOptions::new() - .append(true) - .create(true) - .open(&logfile)?, - ); fuzzer .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) @@ -449,4 +429,23 @@ fn fuzz( // Never reached Ok(()) + + }; + + match Launcher::builder() + .shmem_provider(shmem_provider) + .configuration(EventConfig::AlwaysUnique) + .monitor(monitor) + .run_client(&mut run_client) + .cores(&Cores::from_cmdline("all").unwrap()) + // .broker_port(1337) + // .remote_broker_addr(remote_broker_addr) + //.stdout_file(Some("/dev/null")) + .build() + .launch() + { + Ok(_) | Err(Error::ShuttingDown) => (), + Err(e) => panic!("{:?}", e), + }; + Ok(()) } diff --git a/libafl/src/bolts/llmp.rs b/libafl/src/bolts/llmp.rs index de7b75a189..fd3894a401 100644 --- a/libafl/src/bolts/llmp.rs +++ b/libafl/src/bolts/llmp.rs @@ -2219,11 +2219,12 @@ where loop { match listener.accept() { ListenerStream::Tcp(mut stream, addr) => { - eprintln!( - "New connection: {:?}/{:?}", - addr, - stream.peer_addr().unwrap() - ); + // For some reason stderr is not avalible in child + // eprintln!( + // "New connection: {:?}/{:?}", + // addr, + // stream.peer_addr().unwrap() + // ); // Send initial information, without anyone asking. // This makes it a tiny bit easier to map the broker map for new Clients.