fuzz: explicitly keep or reject fuzzer corpus

When the main fuzzer function returns (), it is equivalent to
returning Corpus::Keep.

In some of the return paths, we want to reject the input so that the
libfuzzer won't spend more time mutating them.

The should make fuzzing more efficient. No functional change intended.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2024-12-30 23:15:22 +00:00 committed by Wei Liu
parent ef88b2778e
commit 6fd5b0f696
13 changed files with 79 additions and 53 deletions

View File

@ -7,7 +7,7 @@
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::Arc; use std::sync::Arc;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -37,11 +37,11 @@ const AVAIL_RING_SIZE: u64 = 6_u64 + 2 * QUEUE_SIZE as u64;
// Used ring size // Used ring size
const USED_RING_SIZE: u64 = 6_u64 + 8 * QUEUE_SIZE as u64; const USED_RING_SIZE: u64 = 6_u64 + 8 * QUEUE_SIZE as u64;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < QUEUE_DATA_SIZE * QUEUE_NUM if bytes.len() < QUEUE_DATA_SIZE * QUEUE_NUM
|| bytes.len() > (QUEUE_DATA_SIZE * QUEUE_NUM + MEM_SIZE) || bytes.len() > (QUEUE_DATA_SIZE * QUEUE_NUM + MEM_SIZE)
{ {
return; return Corpus::Reject;
} }
let mut balloon = virtio_devices::Balloon::new( let mut balloon = virtio_devices::Balloon::new(
@ -61,7 +61,7 @@ fuzz_target!(|bytes| {
// Setup the guest memory with the input bytes // Setup the guest memory with the input bytes
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -108,6 +108,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and balloon device worker thread to return // Wait for the events to finish and balloon device worker thread to return
balloon.wait_for_epoll_threads(); balloon.wait_for_epoll_threads();
Corpus::Keep
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}

View File

@ -17,7 +17,7 @@ use std::{ffi, io};
use block::async_io::DiskFile; use block::async_io::DiskFile;
use block::raw_sync::RawFileDiskSync; use block::raw_sync::RawFileDiskSync;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -40,9 +40,9 @@ const AVAIL_RING_SIZE: u64 = 6_u64 + 2 * QUEUE_SIZE as u64;
// Guest physical address for used ring (requires to 4-bytes aligned) // Guest physical address for used ring (requires to 4-bytes aligned)
const USED_RING_ADDR: u64 = (AVAIL_RING_ADDR + AVAIL_RING_SIZE + 3) & !3_u64; const USED_RING_ADDR: u64 = (AVAIL_RING_ADDR + AVAIL_RING_SIZE + 3) & !3_u64;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < QUEUE_DATA_SIZE || bytes.len() > (QUEUE_DATA_SIZE + MEM_SIZE) { if bytes.len() < QUEUE_DATA_SIZE || bytes.len() > (QUEUE_DATA_SIZE + MEM_SIZE) {
return; return Corpus::Reject;
} }
let queue_data = &bytes[..QUEUE_DATA_SIZE]; let queue_data = &bytes[..QUEUE_DATA_SIZE];
@ -76,7 +76,7 @@ fuzz_target!(|bytes| {
// Setup the guest memory with the input bytes // Setup the guest memory with the input bytes
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -96,6 +96,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and block device worker thread to return // Wait for the events to finish and block device worker thread to return
block.wait_for_epoll_threads(); block.wait_for_epoll_threads();
Corpus::Keep
}); });
fn memfd_create(name: &ffi::CStr, flags: u32) -> Result<RawFd, io::Error> { fn memfd_create(name: &ffi::CStr, flags: u32) -> Result<RawFd, io::Error> {

View File

@ -5,14 +5,14 @@
#![no_main] #![no_main]
use devices::legacy::Cmos; use devices::legacy::Cmos;
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use vm_device::BusDevice; use vm_device::BusDevice;
use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::eventfd::EventFd;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
// Need at least 16 bytes for the test // Need at least 16 bytes for the test
if bytes.len() < 16 { if bytes.len() < 16 {
return; return Corpus::Reject;
} }
let mut below_4g = [0u8; 8]; let mut below_4g = [0u8; 8];
@ -46,4 +46,6 @@ fuzz_target!(|bytes| {
cmos.write(0, offset, &data); cmos.write(0, offset, &data);
} }
} }
Corpus::Keep
}); });

View File

@ -9,7 +9,7 @@ use std::io::Write;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Arc; use std::sync::Arc;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -54,12 +54,12 @@ const QUEUE_BYTES_SIZE: usize = align!(
DESC_TABLE_ALIGN_SIZE DESC_TABLE_ALIGN_SIZE
) as usize; ) as usize;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM + CONSOLE_INPUT_SIZE if bytes.len() < (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM + CONSOLE_INPUT_SIZE
|| bytes.len() || bytes.len()
> (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM + CONSOLE_INPUT_SIZE + MEM_SIZE > (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM + CONSOLE_INPUT_SIZE + MEM_SIZE
{ {
return; return Corpus::Reject;
} }
let (pipe_rx, mut pipe_tx) = create_pipe().unwrap(); let (pipe_rx, mut pipe_tx) = create_pipe().unwrap();
@ -108,10 +108,10 @@ fuzz_target!(|bytes| {
.write_slice(queue_bytes, GuestAddress(BASE_VIRT_QUEUE_ADDR)) .write_slice(queue_bytes, GuestAddress(BASE_VIRT_QUEUE_ADDR))
.is_err() .is_err()
{ {
return; return Corpus::Reject;
} }
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -137,6 +137,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and console device worker thread to return // Wait for the events to finish and console device worker thread to return
console.wait_for_epoll_threads(); console.wait_for_epoll_threads();
Corpus::Keep
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}

View File

@ -8,7 +8,7 @@ use std::path::PathBuf;
use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::{channel, Receiver};
use std::thread; use std::thread;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use micro_http::Request; use micro_http::Request;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use vm_migration::MigratableError; use vm_migration::MigratableError;
@ -27,9 +27,9 @@ use vmm_sys_util::eventfd::EventFd;
static ROUTES: Lazy<Vec<&Box<dyn EndpointHandler + Sync + Send>>> = static ROUTES: Lazy<Vec<&Box<dyn EndpointHandler + Sync + Send>>> =
Lazy::new(|| HTTP_ROUTES.routes.values().collect()); Lazy::new(|| HTTP_ROUTES.routes.values().collect());
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < 2 { if bytes.len() < 2 {
return; return Corpus::Reject;
} }
let route = ROUTES[bytes[0] as usize % ROUTES.len()]; let route = ROUTES[bytes[0] as usize % ROUTES.len()];
@ -53,6 +53,8 @@ fuzz_target!(|bytes| {
exit_evt.write(1).ok(); exit_evt.write(1).ok();
http_receiver_thread.join().unwrap(); http_receiver_thread.join().unwrap();
}; };
Corpus::Keep
}); });
fn generate_request(bytes: &[u8]) -> Option<Request> { fn generate_request(bytes: &[u8]) -> Option<Request> {

View File

@ -7,7 +7,7 @@
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::Arc; use std::sync::Arc;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -54,11 +54,11 @@ const USED_RING_ADDR: u64 = align!(AVAIL_RING_ADDR + AVAIL_RING_SIZE, USED_RING_
// Virtio-queue size in bytes // Virtio-queue size in bytes
const QUEUE_BYTES_SIZE: usize = (USED_RING_ADDR + USED_RING_SIZE - DESC_TABLE_ADDR) as usize; const QUEUE_BYTES_SIZE: usize = (USED_RING_ADDR + USED_RING_SIZE - DESC_TABLE_ADDR) as usize;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) if bytes.len() < (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE)
|| bytes.len() > (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE + MEM_SIZE) || bytes.len() > (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE + MEM_SIZE)
{ {
return; return Corpus::Reject;
} }
let (mut iommu, _) = virtio_devices::Iommu::new( let (mut iommu, _) = virtio_devices::Iommu::new(
@ -91,10 +91,10 @@ fuzz_target!(|bytes| {
.write_slice(queue_bytes, GuestAddress(DESC_TABLE_ADDR)) .write_slice(queue_bytes, GuestAddress(DESC_TABLE_ADDR))
.is_err() .is_err()
{ {
return; return Corpus::Reject;
} }
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -118,6 +118,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and vIOMMU device worker thread to return // Wait for the events to finish and vIOMMU device worker thread to return
iommu.wait_for_epoll_threads(); iommu.wait_for_epoll_threads();
Corpus::Keep
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}

View File

@ -8,7 +8,7 @@
#![no_main] #![no_main]
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use vm_memory::bitmap::AtomicBitmap; use vm_memory::bitmap::AtomicBitmap;
use vm_memory::GuestAddress; use vm_memory::GuestAddress;
@ -18,7 +18,7 @@ const MEM_SIZE: usize = 256 * 1024 * 1024;
// From 'arch::x86_64::layout::CMDLINE_START' // From 'arch::x86_64::layout::CMDLINE_START'
const CMDLINE_START: GuestAddress = GuestAddress(0x20000); const CMDLINE_START: GuestAddress = GuestAddress(0x20000);
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
let payload_config = vmm::vm_config::PayloadConfig { let payload_config = vmm::vm_config::PayloadConfig {
firmware: None, firmware: None,
kernel: None, kernel: None,
@ -29,9 +29,11 @@ fuzz_target!(|bytes| {
}; };
let kernel_cmdline = match vmm::vm::Vm::generate_cmdline(&payload_config) { let kernel_cmdline = match vmm::vm::Vm::generate_cmdline(&payload_config) {
Ok(cmdline) => cmdline, Ok(cmdline) => cmdline,
_ => return, _ => return Corpus::Reject,
}; };
let guest_memory = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); let guest_memory = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
linux_loader::loader::load_cmdline(&guest_memory, CMDLINE_START, &kernel_cmdline).ok(); linux_loader::loader::load_cmdline(&guest_memory, CMDLINE_START, &kernel_cmdline).ok();
Corpus::Keep
}); });

View File

@ -7,7 +7,7 @@
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{BlocksState, Mem, VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{BlocksState, Mem, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -57,11 +57,11 @@ const USED_RING_ADDR: u64 = align!(AVAIL_RING_ADDR + AVAIL_RING_SIZE, USED_RING_
// Virtio-queue size in bytes // Virtio-queue size in bytes
const QUEUE_BYTES_SIZE: usize = (USED_RING_ADDR + USED_RING_SIZE - DESC_TABLE_ADDR) as usize; const QUEUE_BYTES_SIZE: usize = (USED_RING_ADDR + USED_RING_SIZE - DESC_TABLE_ADDR) as usize;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < VIRTIO_MEM_DATA_SIZE + QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE if bytes.len() < VIRTIO_MEM_DATA_SIZE + QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE
|| bytes.len() > (VIRTIO_MEM_DATA_SIZE + QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE + MEM_SIZE) || bytes.len() > (VIRTIO_MEM_DATA_SIZE + QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE + MEM_SIZE)
{ {
return; return Corpus::Reject;
} }
let virtio_mem_data = &bytes[..VIRTIO_MEM_DATA_SIZE]; let virtio_mem_data = &bytes[..VIRTIO_MEM_DATA_SIZE];
@ -86,7 +86,7 @@ fuzz_target!(|bytes| {
.write_slice(queue_bytes, GuestAddress(DESC_TABLE_ADDR)) .write_slice(queue_bytes, GuestAddress(DESC_TABLE_ADDR))
.is_err() .is_err()
{ {
return; return Corpus::Reject;
} }
// Add the memory region for the virtio-mem device // Add the memory region for the virtio-mem device
let mem = mem.insert_region(virtio_mem_region).unwrap(); let mem = mem.insert_region(virtio_mem_region).unwrap();
@ -94,7 +94,7 @@ fuzz_target!(|bytes| {
.write_slice(mem_bytes, GuestAddress(VIRTIO_MEM_REGION_ADDRESS)) .write_slice(mem_bytes, GuestAddress(VIRTIO_MEM_REGION_ADDRESS))
.is_err() .is_err()
{ {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -114,6 +114,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and virtio-mem device worker thread to return // Wait for the events to finish and virtio-mem device worker thread to return
virtio_mem.wait_for_epoll_threads(); virtio_mem.wait_for_epoll_threads();
return Corpus::Keep;
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}

View File

@ -9,7 +9,7 @@ use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::Arc; use std::sync::Arc;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -55,12 +55,12 @@ const QUEUE_BYTES_SIZE: usize = align!(
DESC_TABLE_ALIGN_SIZE DESC_TABLE_ALIGN_SIZE
) as usize; ) as usize;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < TAP_INPUT_SIZE + (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM if bytes.len() < TAP_INPUT_SIZE + (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM
|| bytes.len() || bytes.len()
> TAP_INPUT_SIZE + (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM + MEM_SIZE > TAP_INPUT_SIZE + (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) * QUEUE_NUM + MEM_SIZE
{ {
return; return Corpus::Reject;
} }
let (dummy_tap_frontend, dummy_tap_backend) = create_socketpair().unwrap(); let (dummy_tap_frontend, dummy_tap_backend) = create_socketpair().unwrap();
@ -111,10 +111,10 @@ fuzz_target!(|bytes| {
.write_slice(queue_bytes, GuestAddress(BASE_VIRT_QUEUE_ADDR)) .write_slice(queue_bytes, GuestAddress(BASE_VIRT_QUEUE_ADDR))
.is_err() .is_err()
{ {
return; return Corpus::Reject;
} }
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -155,6 +155,8 @@ fuzz_target!(|bytes| {
// Terminate the thread for the dummy tap backend // Terminate the thread for the dummy tap backend
exit_evt.write(1).ok(); exit_evt.write(1).ok();
tap_backend_thread.join().unwrap(); tap_backend_thread.join().unwrap();
return Corpus::Keep;
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}

View File

@ -10,7 +10,7 @@ use std::sync::Arc;
use std::{ffi, io}; use std::{ffi, io};
use libc::{MAP_NORESERVE, MAP_PRIVATE, PROT_READ, PROT_WRITE}; use libc::{MAP_NORESERVE, MAP_PRIVATE, PROT_READ, PROT_WRITE};
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{Pmem, UserspaceMapping, VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{Pmem, UserspaceMapping, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -35,9 +35,9 @@ const AVAIL_RING_SIZE: u64 = 6_u64 + 2 * QUEUE_SIZE as u64;
// Guest physical address for used ring (requires to 4-bytes aligned) // Guest physical address for used ring (requires to 4-bytes aligned)
const USED_RING_ADDR: u64 = (AVAIL_RING_ADDR + AVAIL_RING_SIZE + 3) & !3_u64; const USED_RING_ADDR: u64 = (AVAIL_RING_ADDR + AVAIL_RING_SIZE + 3) & !3_u64;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < QUEUE_DATA_SIZE || bytes.len() > (QUEUE_DATA_SIZE + MEM_SIZE) { if bytes.len() < QUEUE_DATA_SIZE || bytes.len() > (QUEUE_DATA_SIZE + MEM_SIZE) {
return; return Corpus::Reject;
} }
let mut pmem = create_dummy_pmem(); let mut pmem = create_dummy_pmem();
@ -50,7 +50,7 @@ fuzz_target!(|bytes| {
// Setup the guest memory with the input bytes // Setup the guest memory with the input bytes
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -69,6 +69,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and pmem device worker thread to return // Wait for the events to finish and pmem device worker thread to return
pmem.wait_for_epoll_threads(); pmem.wait_for_epoll_threads();
Corpus::Keep
}); });
fn memfd_create_with_size(name: &ffi::CStr, flags: u32, size: usize) -> Result<RawFd, io::Error> { fn memfd_create_with_size(name: &ffi::CStr, flags: u32, size: usize) -> Result<RawFd, io::Error> {

View File

@ -12,14 +12,14 @@ use std::mem::size_of;
use std::os::unix::io::{FromRawFd, RawFd}; use std::os::unix::io::{FromRawFd, RawFd};
use block::qcow::{QcowFile, RawFile}; use block::qcow::{QcowFile, RawFile};
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
// Take the first 64 bits of data as an address and the next 64 bits as data to // Take the first 64 bits of data as an address and the next 64 bits as data to
// store there. The rest of the data is used as a qcow image. // store there. The rest of the data is used as a qcow image.
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < 16 { if bytes.len() < 16 {
// Need an address and data, each are 8 bytes. // Need an address and data, each are 8 bytes.
return; return Corpus::Reject;
} }
let mut disk_image = Cursor::new(bytes); let mut disk_image = Cursor::new(bytes);
let addr = read_u64(&mut disk_image); let addr = read_u64(&mut disk_image);
@ -33,6 +33,8 @@ fuzz_target!(|bytes| {
let _ = qcow.write_all(&value.to_le_bytes()); let _ = qcow.write_all(&value.to_le_bytes());
} }
} }
Corpus::Keep
}); });
fn read_u64<T: Read>(readable: &mut T) -> u64 { fn read_u64<T: Read>(readable: &mut T) -> u64 {

View File

@ -7,7 +7,7 @@
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::Arc; use std::sync::Arc;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -52,11 +52,11 @@ const USED_RING_ADDR: u64 = align!(AVAIL_RING_ADDR + AVAIL_RING_SIZE, USED_RING_
// Virtio-queue size in bytes // Virtio-queue size in bytes
const QUEUE_BYTES_SIZE: usize = (USED_RING_ADDR + USED_RING_SIZE - DESC_TABLE_ADDR) as usize; const QUEUE_BYTES_SIZE: usize = (USED_RING_ADDR + USED_RING_SIZE - DESC_TABLE_ADDR) as usize;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE) if bytes.len() < (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE)
|| bytes.len() > (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE + MEM_SIZE) || bytes.len() > (QUEUE_DATA_SIZE + QUEUE_BYTES_SIZE + MEM_SIZE)
{ {
return; return Corpus::Reject;
} }
let mut rng = virtio_devices::Rng::new( let mut rng = virtio_devices::Rng::new(
@ -86,10 +86,10 @@ fuzz_target!(|bytes| {
.write_slice(queue_bytes, GuestAddress(DESC_TABLE_ADDR)) .write_slice(queue_bytes, GuestAddress(DESC_TABLE_ADDR))
.is_err() .is_err()
{ {
return; return Corpus::Reject;
} }
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -108,6 +108,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and rng device worker thread to return // Wait for the events to finish and rng device worker thread to return
rng.wait_for_epoll_threads(); rng.wait_for_epoll_threads();
Corpus::Keep
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}

View File

@ -7,7 +7,7 @@
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::Arc; use std::sync::Arc;
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::{fuzz_target, Corpus};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_devices::{VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
@ -30,9 +30,9 @@ const AVAIL_RING_SIZE: u64 = 6_u64 + 2 * QUEUE_SIZE as u64;
// Guest physical address for used ring (requires to 4-bytes aligned) // Guest physical address for used ring (requires to 4-bytes aligned)
const USED_RING_ADDR: u64 = (AVAIL_RING_ADDR + AVAIL_RING_SIZE + 3) & !3_u64; const USED_RING_ADDR: u64 = (AVAIL_RING_ADDR + AVAIL_RING_SIZE + 3) & !3_u64;
fuzz_target!(|bytes| { fuzz_target!(|bytes: &[u8]| -> Corpus {
if bytes.len() < QUEUE_DATA_SIZE || bytes.len() > (QUEUE_DATA_SIZE + MEM_SIZE) { if bytes.len() < QUEUE_DATA_SIZE || bytes.len() > (QUEUE_DATA_SIZE + MEM_SIZE) {
return; return Corpus::Reject;
} }
let mut watchdog = virtio_devices::Watchdog::new( let mut watchdog = virtio_devices::Watchdog::new(
@ -53,7 +53,7 @@ fuzz_target!(|bytes| {
// Setup the guest memory with the input bytes // Setup the guest memory with the input bytes
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() { if mem.write_slice(mem_bytes, GuestAddress(0 as u64)).is_err() {
return; return Corpus::Reject;
} }
let guest_memory = GuestMemoryAtomic::new(mem); let guest_memory = GuestMemoryAtomic::new(mem);
@ -73,6 +73,8 @@ fuzz_target!(|bytes| {
// Wait for the events to finish and watchdog device worker thread to return // Wait for the events to finish and watchdog device worker thread to return
watchdog.wait_for_epoll_threads(); watchdog.wait_for_epoll_threads();
Corpus::Keep
}); });
pub struct NoopVirtioInterrupt {} pub struct NoopVirtioInterrupt {}