fuzz: Add new fuzzer for emulated serial device

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2022-07-26 16:30:56 +01:00
parent f4e2198767
commit e4211272ad
3 changed files with 84 additions and 1 deletions

2
fuzz/Cargo.lock generated
View File

@ -178,6 +178,7 @@ version = "0.0.0"
dependencies = [
"block_util",
"cloud-hypervisor",
"devices",
"libc",
"libfuzzer-sys",
"qcow",
@ -185,6 +186,7 @@ dependencies = [
"vhdx",
"virtio-devices",
"virtio-queue",
"vm-device",
"vm-memory",
"vm-virtio",
"vmm-sys-util",

View File

@ -10,6 +10,7 @@ cargo-fuzz = true
[dependencies]
block_util = { path = "../block_util" }
devices = { path = "../devices" }
libc = "0.2.126"
libfuzzer-sys = "0.4.3"
qcow = { path = "../qcow" }
@ -18,8 +19,9 @@ vhdx = { path = "../vhdx" }
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.4.0"
vmm-sys-util = "0.10.0"
vm-virtio = { path = "../vm-virtio" }
vm-memory = "0.8.0"
vm-device = { path = "../vm-device" }
vm-virtio = { path = "../vm-virtio" }
[dependencies.cloud-hypervisor]
path = ".."
@ -50,3 +52,9 @@ name = "vhdx"
path = "fuzz_targets/vhdx.rs"
test = false
doc = false
[[bin]]
name = "serial"
path = "fuzz_targets/serial.rs"
test = false
doc = false

View File

@ -0,0 +1,73 @@
// Copyright © 2022 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
#![no_main]
use devices::legacy::Serial;
use libc::EFD_NONBLOCK;
use libfuzzer_sys::fuzz_target;
use std::sync::Arc;
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig, InterruptSourceGroup};
use vm_device::BusDevice;
use vmm_sys_util::eventfd::EventFd;
fuzz_target!(|bytes| {
let mut serial = Serial::new_sink(
"serial".into(),
Arc::new(TestInterrupt::new(EventFd::new(EFD_NONBLOCK).unwrap())),
);
let mut i = 0;
while i < bytes.len() {
let choice = bytes.get(i).unwrap_or(&0) % 3;
i += 1;
match choice {
0 => {
let offset = (bytes.get(i).unwrap_or(&0) % 8) as u64;
i += 1;
let mut out_bytes = vec![0];
serial.read(0, offset, &mut out_bytes);
}
1 => {
let offset = (bytes.get(i).unwrap_or(&0) % 8) as u64;
i += 1;
let data = vec![*bytes.get(i).unwrap_or(&0)];
i += 1;
serial.write(0, offset, &data);
}
_ => {
let data = vec![*bytes.get(i).unwrap_or(&0)];
i += 1;
serial.queue_input_bytes(&data).ok();
}
}
}
});
struct TestInterrupt {
event_fd: EventFd,
}
impl InterruptSourceGroup for TestInterrupt {
fn trigger(&self, _index: InterruptIndex) -> Result<(), std::io::Error> {
self.event_fd.write(1)
}
fn update(
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
) -> Result<(), std::io::Error> {
Ok(())
}
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
Some(self.event_fd.try_clone().unwrap())
}
}
impl TestInterrupt {
fn new(event_fd: EventFd) -> Self {
TestInterrupt { event_fd }
}
}