diff --git a/hbvm/fuzz/.gitignore b/hbvm/fuzz/.gitignore new file mode 100644 index 00000000..23a1dd82 --- /dev/null +++ b/hbvm/fuzz/.gitignore @@ -0,0 +1,5 @@ +target +artifacts +corpus +coverage +Cargo.lock diff --git a/hbvm/fuzz/Cargo.toml b/hbvm/fuzz/Cargo.toml new file mode 100644 index 00000000..42566bd3 --- /dev/null +++ b/hbvm/fuzz/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "hbvm-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" + +[dependencies.hbvm] +path = ".." + +[dependencies.hbbytecode] +path = "../../hbbytecode" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +debug = 1 + +[[bin]] +name = "vm" +path = "fuzz_targets/vm.rs" +test = false +doc = false diff --git a/hbvm/fuzz/fuzz_targets/vm.rs b/hbvm/fuzz/fuzz_targets/vm.rs new file mode 100644 index 00000000..aa6d7ccf --- /dev/null +++ b/hbvm/fuzz/fuzz_targets/vm.rs @@ -0,0 +1,82 @@ +#![no_main] + +use { + hbvm::{ + mem::{ + softpaging::{ + paging::{PageTable, Permission}, + HandlePageFault, PageSize, SoftPagedMem, + }, + Address, MemoryAccessReason, + }, + Vm, + }, + libfuzzer_sys::fuzz_target, +}; + +fuzz_target!(|data: &[u8]| { + let mut vm = unsafe { + Vm::<_, 16384>::new( + SoftPagedMem::<_, true> { + pf_handler: TestTrapHandler, + program: data, + root_pt: Box::into_raw(Default::default()), + icache: Default::default(), + }, + Address::new(4), + ) + }; + + // Alloc and map some memory + let pages = [ + alloc_and_map(&mut vm.memory, 0), + alloc_and_map(&mut vm.memory, 4096), + ]; + + // Run VM + let _ = vm.run(); + + // Unmap and dealloc the memory + for (i, page) in pages.into_iter().enumerate() { + unmap_and_dealloc(&mut vm.memory, page, i as u64 * 4096); + } + + let _ = unsafe { Box::from_raw(vm.memory.root_pt) }; +}); + +fn alloc_and_map(memory: &mut SoftPagedMem, at: u64) -> *mut u8 { + let ptr = Box::into_raw(Box::::default()).cast(); + unsafe { + memory + .map(ptr, Address::new(at), Permission::Write, PageSize::Size4K) + .unwrap() + }; + ptr +} + +fn unmap_and_dealloc(memory: &mut SoftPagedMem, ptr: *mut u8, from: u64) { + memory.unmap(Address::new(from)).unwrap(); + let _ = unsafe { Box::from_raw(ptr.cast::()) }; +} + +#[repr(align(4096))] +struct Page([u8; 4096]); +impl Default for Page { + fn default() -> Self { + unsafe { std::mem::MaybeUninit::zeroed().assume_init() } + } +} + +struct TestTrapHandler; +impl HandlePageFault for TestTrapHandler { + fn page_fault( + &mut self, + _: MemoryAccessReason, + _: &mut PageTable, + _: Address, + _: PageSize, + _: *mut u8, + ) -> bool { + false + } +}