diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 135475d8d4..91a1be6bd6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,4 +6,8 @@ repos: - id: fmt name: fmt entry: scripts/fmt_all.sh check - language: script \ No newline at end of file + language: script + - id: taplo + name: taplo + entry: taplo format --check + language: system diff --git a/fuzzers/binary_only/fuzzbench_qemu/Cargo.toml b/fuzzers/binary_only/fuzzbench_qemu/Cargo.toml index 778d81194d..0604ccf50e 100644 --- a/fuzzers/binary_only/fuzzbench_qemu/Cargo.toml +++ b/fuzzers/binary_only/fuzzbench_qemu/Cargo.toml @@ -31,6 +31,7 @@ libafl_qemu = { path = "../../../libafl_qemu", features = [ ] } libafl_targets = { path = "../../../libafl_targets", version = "0.13.2" } +env_logger = "0.11.5" log = { version = "0.4.22", features = ["release_max_level_info"] } clap = { version = "4.5.18", features = ["default"] } nix = { version = "0.29.0", features = ["fs"] } diff --git a/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs b/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs index 909a6511d0..b41940adfb 100644 --- a/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs +++ b/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs @@ -171,10 +171,11 @@ fn fuzz( logfile: PathBuf, timeout: Duration, ) -> Result<(), Error> { + env_logger::init(); env::remove_var("LD_LIBRARY_PATH"); let args: Vec = env::args().collect(); - let qemu = Qemu::init(&args).unwrap(); + let qemu = Qemu::init(&args).expect("QEMU init failed"); // let (emu, asan) = init_with_asan(&mut args, &mut env).unwrap(); let mut elf_buffer = Vec::new(); @@ -197,7 +198,8 @@ fn fuzz( let stack_ptr: u64 = qemu.read_reg(Regs::Sp).unwrap(); let mut ret_addr = [0; 8]; - unsafe { qemu.read_mem(stack_ptr, &mut ret_addr) }; + qemu.read_mem(stack_ptr, &mut ret_addr) + .expect("Error while reading QEMU memory."); let ret_addr = u64::from_le_bytes(ret_addr); println!("Stack pointer = {stack_ptr:#x}"); @@ -337,7 +339,7 @@ fn fuzz( } unsafe { - qemu.write_mem(input_addr, buf); + qemu.write_mem_unchecked(input_addr, buf); qemu.write_reg(Regs::Rdi, input_addr).unwrap(); qemu.write_reg(Regs::Rsi, len as GuestReg).unwrap(); @@ -397,7 +399,7 @@ fn fuzz( println!("Failed to load initial corpus at {:?}", &seed_dir); process::exit(0); }); - println!("We imported {} inputs from disk.", state.corpus().count()); + println!("We imported {} input(s) from disk.", state.corpus().count()); } let tracing = ShadowTracingStage::new(&mut executor); diff --git a/libafl/src/corpus/inmemory_ondisk.rs b/libafl/src/corpus/inmemory_ondisk.rs index 02105b7d9b..58be73441d 100644 --- a/libafl/src/corpus/inmemory_ondisk.rs +++ b/libafl/src/corpus/inmemory_ondisk.rs @@ -423,14 +423,20 @@ impl InMemoryOnDiskCorpus { let mut tmpfile = File::create(&tmpfile_path)?; + let json_error = + |err| Error::serialize(format!("Failed to json-ify metadata: {err:?}")); + let serialized = match self.meta_format.as_ref().unwrap() { OnDiskMetadataFormat::Postcard => postcard::to_allocvec(&ondisk_meta)?, - OnDiskMetadataFormat::Json => serde_json::to_vec(&ondisk_meta)?, - OnDiskMetadataFormat::JsonPretty => serde_json::to_vec_pretty(&ondisk_meta)?, - #[cfg(feature = "gzip")] - OnDiskMetadataFormat::JsonGzip => { - GzipCompressor::new().compress(&serde_json::to_vec_pretty(&ondisk_meta)?) + OnDiskMetadataFormat::Json => { + serde_json::to_vec(&ondisk_meta).map_err(json_error)? } + OnDiskMetadataFormat::JsonPretty => { + serde_json::to_vec_pretty(&ondisk_meta).map_err(json_error)? + } + #[cfg(feature = "gzip")] + OnDiskMetadataFormat::JsonGzip => GzipCompressor::new() + .compress(&serde_json::to_vec_pretty(&ondisk_meta).map_err(json_error)?), }; tmpfile.write_all(&serialized)?; fs::rename(&tmpfile_path, &metafile_path)?; diff --git a/libafl/src/generators/nautilus.rs b/libafl/src/generators/nautilus.rs index ec2a0a45e2..4f7d76009f 100644 --- a/libafl/src/generators/nautilus.rs +++ b/libafl/src/generators/nautilus.rs @@ -86,7 +86,8 @@ impl NautilusContext { /// Create a new [`NautilusContext`] from a file pub fn from_file>(tree_depth: usize, grammar_file: P) -> Result { - if grammar_file.as_ref().extension().unwrap_or_default() == "py" { + let grammar_file = grammar_file.as_ref(); + if grammar_file.extension().unwrap_or_default() == "py" { log::debug!("Creating NautilusContext from python grammar"); let ctx = python_grammar_loader::load_python_grammar( fs::read_to_string(grammar_file)?.as_str(), @@ -96,7 +97,11 @@ impl NautilusContext { log::debug!("Creating NautilusContext from json grammar"); let file = fs::File::open(grammar_file)?; let reader = BufReader::new(file); - let rules: Vec> = serde_json::from_reader(reader)?; + let rules: Vec> = serde_json::from_reader(reader).map_err(|err| { + Error::illegal_argument(format!( + "Error loading context from json grammar file {grammar_file:?}: {err:?}" + )) + })?; Ok(Self::new(tree_depth, &rules)) } } diff --git a/libafl/src/observers/profiling.rs b/libafl/src/observers/profiling.rs index 88eb8a1928..8f73169f26 100644 --- a/libafl/src/observers/profiling.rs +++ b/libafl/src/observers/profiling.rs @@ -85,9 +85,12 @@ impl ProfilingObserver { where P: AsRef, { - let f = File::open(json_path)?; + let f = File::open(json_path.as_ref())?; let reader = BufReader::new(f); - let analysis_data: AnalysisData = serde_json::from_reader(reader)?; + let analysis_data: AnalysisData = serde_json::from_reader(reader).map_err(|err| { + let path = json_path.as_ref().to_string_lossy(); + Error::illegal_argument(format!("Failed to read from path {path}: {err:?}")) + })?; // debug /* for record in &analysis_data.data { diff --git a/libafl_bolts/Cargo.toml b/libafl_bolts/Cargo.toml index 409ceaba96..f55c768c14 100644 --- a/libafl_bolts/Cargo.toml +++ b/libafl_bolts/Cargo.toml @@ -44,8 +44,6 @@ document-features = ["dep:document-features"] ## Enables features that need rust's `std` lib to work, like print, env, ... support std = [ - "serde_json", - "serde_json/std", "hostname", "nix", "serde/std", @@ -143,9 +141,6 @@ ahash = { workspace = true, optional = true } # The hash function already used i backtrace = { workspace = true, default-features = true, optional = true } # Used to get the stacktrace in StacktraceObserver ctor = { optional = true, version = "0.2.8" } -serde_json = { workspace = true, optional = true, default-features = false, features = [ - "alloc", -] } miniz_oxide = { version = "0.8.0", optional = true } hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? rand_core = { version = "0.6.4", optional = true } diff --git a/libafl_bolts/src/lib.rs b/libafl_bolts/src/lib.rs index e0cf8ce665..4c7bec9b13 100644 --- a/libafl_bolts/src/lib.rs +++ b/libafl_bolts/src/lib.rs @@ -532,14 +532,6 @@ impl From for Error { } } -/// Stringify the json serializer error -#[cfg(feature = "std")] -impl From for Error { - fn from(err: serde_json::Error) -> Self { - Self::serialize(format!("{err:?}")) - } -} - #[cfg(all(unix, feature = "std"))] impl From for Error { fn from(err: nix::Error) -> Self { diff --git a/libafl_bolts/src/serdeany.rs b/libafl_bolts/src/serdeany.rs index 37ec99dc6c..bbbf65d52a 100644 --- a/libafl_bolts/src/serdeany.rs +++ b/libafl_bolts/src/serdeany.rs @@ -266,22 +266,6 @@ pub mod serdeany_registry { } } - /* - #[cfg(feature = "anymap_debug")] - impl fmt::Debug for SerdeAnyMap { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let json = serde_json::to_string(&self); - write!(f, "SerdeAnyMap: [{:?}]", json) - } - } - - #[cfg(not(feature = "anymap_debug"))] - impl fmt::Debug for SerdeAnyMap { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "SerdeAnymap with {} elements", self.len()) - } - }*/ - #[allow(unused_qualifications)] impl SerdeAnyMap { /// Get an element from the map. diff --git a/libafl_qemu/libafl_qemu_build/src/bindings.rs b/libafl_qemu/libafl_qemu_build/src/bindings.rs index f386fec00b..1733cff770 100644 --- a/libafl_qemu/libafl_qemu_build/src/bindings.rs +++ b/libafl_qemu/libafl_qemu_build/src/bindings.rs @@ -80,7 +80,6 @@ const WRAPPER_HEADER: &str = r#" #include "tcg/tcg.h" #include "tcg/tcg-op.h" #include "tcg/tcg-internal.h" -#include "exec/helper-head.h" #include "qemu/plugin-memory.h" diff --git a/libafl_qemu/libafl_qemu_build/src/build.rs b/libafl_qemu/libafl_qemu_build/src/build.rs index c879da04fd..6828b3fea3 100644 --- a/libafl_qemu/libafl_qemu_build/src/build.rs +++ b/libafl_qemu/libafl_qemu_build/src/build.rs @@ -11,7 +11,7 @@ use crate::cargo_add_rpath; pub const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge"; pub const QEMU_DIRNAME: &str = "qemu-libafl-bridge"; -pub const QEMU_REVISION: &str = "c3c9c2128566ff325aa1a2bdcedde717f7d86e2c"; +pub const QEMU_REVISION: &str = "b01a0bc334cf11bfc5e8f121d9520ef7f47dbcd1"; #[allow(clippy::module_name_repetitions)] pub struct BuildResult { @@ -158,7 +158,7 @@ fn configure_qemu( .arg("--disable-linux-aio") .arg("--disable-linux-io-uring") .arg("--disable-linux-user") - .arg("--disable-live-block-migration") + // .arg("--disable-live-block-migration") .arg("--disable-lzfse") .arg("--disable-lzo") .arg("--disable-l2tpv3") @@ -174,7 +174,7 @@ fn configure_qemu( .arg("--disable-pa") .arg("--disable-parallels") .arg("--disable-png") - .arg("--disable-pvrdma") + // .arg("--disable-pvrdma") .arg("--disable-qcow1") .arg("--disable-qed") .arg("--disable-qga-vss") diff --git a/libafl_qemu/src/modules/usermode/asan_guest.rs b/libafl_qemu/src/modules/usermode/asan_guest.rs index 2572c204df..567d98048e 100644 --- a/libafl_qemu/src/modules/usermode/asan_guest.rs +++ b/libafl_qemu/src/modules/usermode/asan_guest.rs @@ -123,7 +123,12 @@ pub struct AsanGuestModule { mappings: Vec, } -#[cfg(any(cpu_target = "aarch64", cpu_target = "x86_64", feature = "clippy"))] +#[cfg(any( + cpu_target = "aarch64", + cpu_target = "x86_64", + cpu_target = "riscv64", + feature = "clippy" +))] impl AsanGuestModule { const HIGH_SHADOW_START: GuestAddr = 0x02008fff7000; const HIGH_SHADOW_END: GuestAddr = 0x10007fff7fff; @@ -135,7 +140,8 @@ impl AsanGuestModule { cpu_target = "arm", cpu_target = "i386", cpu_target = "mips", - cpu_target = "ppc" + cpu_target = "ppc", + cpu_target = "riscv32", ))] impl AsanGuestModule { const HIGH_SHADOW_START: GuestAddr = 0x28000000; diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index ec4fe7db41..e20cfd466e 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -8,15 +8,16 @@ use thread_local::ThreadLocal; #[cfg(any(cpu_target = "arm", cpu_target = "i386", cpu_target = "mips"))] use crate::SYS_fstatat64; -#[cfg(not(cpu_target = "arm"))] +#[cfg(not(any(cpu_target = "arm", cpu_target = "riscv32")))] use crate::SYS_mmap; -#[cfg(any(cpu_target = "arm", cpu_target = "mips"))] +#[cfg(any(cpu_target = "arm", cpu_target = "mips", cpu_target = "riscv32"))] use crate::SYS_mmap2; #[cfg(not(any( cpu_target = "arm", cpu_target = "mips", cpu_target = "i386", - cpu_target = "ppc" + cpu_target = "ppc", + cpu_target = "riscv32", )))] use crate::SYS_newfstatat; use crate::{ @@ -26,9 +27,10 @@ use crate::{ NOP_ADDRESS_FILTER, }, qemu::{Hook, SyscallHookResult}, - Qemu, SYS_brk, SYS_fstat, SYS_fstatfs, SYS_futex, SYS_getrandom, SYS_mprotect, SYS_mremap, - SYS_munmap, SYS_pread64, SYS_read, SYS_readlinkat, SYS_statfs, + Qemu, SYS_brk, SYS_mprotect, SYS_mremap, SYS_munmap, SYS_pread64, SYS_read, SYS_readlinkat, }; +#[cfg(not(cpu_target = "riscv32"))] +use crate::{SYS_fstat, SYS_fstatfs, SYS_futex, SYS_getrandom, SYS_statfs}; // TODO use the functions provided by Qemu pub const SNAPSHOT_PAGE_SIZE: usize = 4096; @@ -804,6 +806,7 @@ where let h = emulator_modules.get_mut::().unwrap(); h.access(a2, a3 as usize); } + #[cfg(not(cpu_target = "riscv32"))] SYS_futex => { let h = emulator_modules.get_mut::().unwrap(); h.access(a0, a3 as usize); @@ -812,7 +815,8 @@ where cpu_target = "arm", cpu_target = "i386", cpu_target = "mips", - cpu_target = "ppc" + cpu_target = "ppc", + cpu_target = "riscv32" )))] SYS_newfstatat => { if a2 != 0 { @@ -827,10 +831,12 @@ where h.access(a2, 4096); // stat is not greater than a page } } - SYS_statfs | SYS_fstatfs | SYS_fstat => { + #[cfg(not(cpu_target = "riscv32"))] + SYS_statfs | SYS_fstat | SYS_fstatfs => { let h = emulator_modules.get_mut::().unwrap(); h.access(a1, 4096); // stat is not greater than a page } + #[cfg(not(cpu_target = "riscv32"))] SYS_getrandom => { let h = emulator_modules.get_mut::().unwrap(); h.access(a0, a1 as usize); @@ -855,7 +861,7 @@ where // TODO handle huge pages - #[cfg(any(cpu_target = "arm", cpu_target = "mips"))] + #[cfg(any(cpu_target = "arm", cpu_target = "mips", cpu_target = "riscv32"))] if sys_const == SYS_mmap2 { if let Ok(prot) = MmapPerms::try_from(a2 as i32) { let h = emulator_modules.get_mut::().unwrap(); @@ -863,7 +869,7 @@ where } } - #[cfg(not(cpu_target = "arm"))] + #[cfg(not(any(cpu_target = "arm", cpu_target = "riscv32")))] if sys_const == SYS_mmap { if let Ok(prot) = MmapPerms::try_from(a2 as i32) { let h = emulator_modules.get_mut::().unwrap(); diff --git a/scripts/parallellize_cargo_check.py b/scripts/parallellize_cargo_check.py index 9e5ca05e7b..d05ee64a24 100755 --- a/scripts/parallellize_cargo_check.py +++ b/scripts/parallellize_cargo_check.py @@ -23,7 +23,7 @@ "--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive " "--no-dev-deps --exclude libafl_libfuzzer --exclude libafl_qemu --exclude libafl_qemu_sys --print-command-list;" "DOCS_RS=1 cargo hack check -p libafl_qemu -p libafl_qemu_sys --each-feature --clean-per-run " - "--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive " + "--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive,slirp " "--no-dev-deps --features usermode --print-command-list" )