diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index d9d709f14..83e03e805 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -169,6 +169,7 @@ dependencies = [ "epoll", "libc", "libfuzzer-sys", + "linux-loader", "micro_http", "net_util", "once_cell", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index a97bae69c..4ab3d9869 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -14,6 +14,7 @@ devices = { path = "../devices" } epoll = "4.3.1" libc = "0.2.138" libfuzzer-sys = "0.4.5" +linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] } micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" } net_util = { path = "../net_util" } once_cell = "1.16.0" @@ -75,6 +76,12 @@ path = "fuzz_targets/iommu.rs" test = false doc = false +[[bin]] +name = "linux_loader" +path = "fuzz_targets/linux_loader.rs" +test = false +doc = false + [[bin]] name = "mem" path = "fuzz_targets/mem.rs" diff --git a/fuzz/fuzz_targets/linux_loader.rs b/fuzz/fuzz_targets/linux_loader.rs new file mode 100644 index 000000000..54de31ae2 --- /dev/null +++ b/fuzz/fuzz_targets/linux_loader.rs @@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Copyright © 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause + +#![no_main] + +use libfuzzer_sys::fuzz_target; +use linux_loader::loader::KernelLoader; +use std::ffi; +use std::fs::File; +use std::io; +use std::io::{Seek, SeekFrom, Write}; +use std::os::unix::io::{FromRawFd, RawFd}; +use vm_memory::{bitmap::AtomicBitmap, GuestAddress}; + +type GuestMemoryMmap = vm_memory::GuestMemoryMmap; + +const MEM_SIZE: usize = 256 * 1024 * 1024; +// From 'arch::x86_64::layout::HIGH_RAM_START' +const HIGH_RAM_START: GuestAddress = GuestAddress(0x100000); + +fuzz_target!(|bytes| { + let shm = memfd_create(&ffi::CString::new("fuzz_load_kernel").unwrap(), 0).unwrap(); + let mut kernel_file: File = unsafe { File::from_raw_fd(shm) }; + kernel_file.write_all(&bytes).unwrap(); + kernel_file.seek(SeekFrom::Start(0)).unwrap(); + + let guest_memory = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); + linux_loader::loader::elf::Elf::load( + &guest_memory, + None, + &mut kernel_file, + Some(HIGH_RAM_START), + ) + .ok(); +}); + +fn memfd_create(name: &ffi::CStr, flags: u32) -> Result { + let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) }; + + if res < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(res as RawFd) + } +}