Skip to content

Commit

Permalink
fuzz: add virtio-blk target
Browse files Browse the repository at this point in the history
Add a new target to fuzz parsing and executing virtio-blk requests
from descriptor chains. This new target mimicks some aspects of the
virtio-vsock one. It uses a memfd file to simulate an actual backend
for the device, using the backend-stdio feature of the crate.

Signed-off-by: Carlos López <carlos.lopez@suse.com>
00xc authored and epilys committed Oct 25, 2023

Verified

This commit was signed with the committer’s verified signature.
joshcooper Josh Cooper
1 parent f69ec8a commit 23be8dd
Showing 5 changed files with 69 additions and 0 deletions.
6 changes: 6 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -16,11 +16,13 @@ cargo-fuzz = true
bincode = "1.3.3"
libfuzzer-sys = "0.4"
serde = "1.0.63"
memfd = "0.6.3"
virtio-queue = { path = "../crates/virtio-queue", features = ["test-utils"] }
virtio-vsock = { path = "../crates/devices/virtio-vsock" }
virtio-queue-ser = { path = "../crates/virtio-queue-ser" }
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic"] }
common = { path = "common" }
virtio-blk = { path = "../crates/devices/virtio-blk", features = ["backend-stdio"] }

[[bin]]
name = "virtio_queue"
@@ -33,3 +35,7 @@ path = "fuzz_targets/vsock.rs"
[[bin]]
name = "virtio_queue_ser"
path = "fuzz_targets/virtio_queue_ser.rs"

[[bin]]
name = "blk"
path = "fuzz_targets/blk.rs"
1 change: 1 addition & 0 deletions fuzz/common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -12,4 +12,5 @@ virtio-bindings = { path = "../../crates/virtio-bindings" }
virtio-queue = { path = "../../crates/virtio-queue", features = ["test-utils"] }
virtio-vsock = { path = "../../crates/devices/virtio-vsock" }
virtio-queue-ser = { path = "../../crates/virtio-queue-ser" }
virtio-blk = { path = "../../crates/devices/virtio-blk" }
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic"] }
10 changes: 10 additions & 0 deletions fuzz/common/src/blk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::FuzzingDescriptor;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct BlkInput {
pub descriptors: Vec<FuzzingDescriptor>,
pub guestmem: Vec<(u64, Vec<u8>)>,
pub features: u64,
pub device_id: Option<[u8; 20]>,
}
1 change: 1 addition & 0 deletions fuzz/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ use vm_memory::GuestMemoryMmap;

use serde::{Deserialize, Serialize};

pub mod blk;
pub mod virtio_queue;
pub mod virtio_queue_ser;
pub mod vsock;
51 changes: 51 additions & 0 deletions fuzz/fuzz_targets/blk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#![no_main]

use common::blk::BlkInput;
use common::virtio_queue::DEFAULT_QUEUE_SIZE;
use libfuzzer_sys::fuzz_target;
use std::hint::black_box;
use virtio_blk::request::Request;
use virtio_blk::stdio_executor::StdIoBackend;
use virtio_queue::{mock::MockSplitQueue, Descriptor};
use vm_memory::{Bytes, GuestAddress, GuestMemoryMmap};

fuzz_target!(|data: &[u8]| {
let Ok(fuzz_input) = bincode::deserialize::<BlkInput>(data) else {
return;
};

let start_addr = GuestAddress(0x1000);
// Create and randomly populate the guest memory
let m = GuestMemoryMmap::<()>::from_ranges(&[(start_addr, 0x11000)]).unwrap();
for (addr, mem) in fuzz_input.guestmem.iter() {
let _ = m.write_slice(mem, GuestAddress(*addr));
}

let vq = MockSplitQueue::create(&m, start_addr, DEFAULT_QUEUE_SIZE);

let descriptors: Vec<Descriptor> = fuzz_input
.descriptors
.iter()
.map(|desc| (*desc).into())
.collect();

// A backing in-memory file
let memfile = memfd::MemfdOptions::default()
.create("fuzzfile")
.unwrap()
.into_file();

// A backend that can execute a virtio-blk request
let mut backend = StdIoBackend::new(memfile, fuzz_input.features).unwrap();
if let Some(id) = fuzz_input.device_id {
backend = backend.with_device_id(id);
}

// Build a descriptor chain, parse and execute a request
if let Ok(mut chain) = vq.build_desc_chain(&descriptors) {
if let Ok(req) = Request::parse(&mut chain) {
// Ensure the compiler does not optimize the request away
let _ = black_box(backend.process_request(&m, &req));
};
}
});

0 comments on commit 23be8dd

Please sign in to comment.