Skip to content

Commit 23be8dd

Browse files
00xcepilys
authored andcommitted
fuzz: add virtio-blk target
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 <[email protected]>
1 parent f69ec8a commit 23be8dd

File tree

5 files changed

+69
-0
lines changed

5 files changed

+69
-0
lines changed

fuzz/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ cargo-fuzz = true
1616
bincode = "1.3.3"
1717
libfuzzer-sys = "0.4"
1818
serde = "1.0.63"
19+
memfd = "0.6.3"
1920
virtio-queue = { path = "../crates/virtio-queue", features = ["test-utils"] }
2021
virtio-vsock = { path = "../crates/devices/virtio-vsock" }
2122
virtio-queue-ser = { path = "../crates/virtio-queue-ser" }
2223
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic"] }
2324
common = { path = "common" }
25+
virtio-blk = { path = "../crates/devices/virtio-blk", features = ["backend-stdio"] }
2426

2527
[[bin]]
2628
name = "virtio_queue"
@@ -33,3 +35,7 @@ path = "fuzz_targets/vsock.rs"
3335
[[bin]]
3436
name = "virtio_queue_ser"
3537
path = "fuzz_targets/virtio_queue_ser.rs"
38+
39+
[[bin]]
40+
name = "blk"
41+
path = "fuzz_targets/blk.rs"

fuzz/common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ virtio-bindings = { path = "../../crates/virtio-bindings" }
1212
virtio-queue = { path = "../../crates/virtio-queue", features = ["test-utils"] }
1313
virtio-vsock = { path = "../../crates/devices/virtio-vsock" }
1414
virtio-queue-ser = { path = "../../crates/virtio-queue-ser" }
15+
virtio-blk = { path = "../../crates/devices/virtio-blk" }
1516
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic"] }

fuzz/common/src/blk.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use crate::FuzzingDescriptor;
2+
use serde::{Deserialize, Serialize};
3+
4+
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
5+
pub struct BlkInput {
6+
pub descriptors: Vec<FuzzingDescriptor>,
7+
pub guestmem: Vec<(u64, Vec<u8>)>,
8+
pub features: u64,
9+
pub device_id: Option<[u8; 20]>,
10+
}

fuzz/common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use vm_memory::GuestMemoryMmap;
66

77
use serde::{Deserialize, Serialize};
88

9+
pub mod blk;
910
pub mod virtio_queue;
1011
pub mod virtio_queue_ser;
1112
pub mod vsock;

fuzz/fuzz_targets/blk.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![no_main]
2+
3+
use common::blk::BlkInput;
4+
use common::virtio_queue::DEFAULT_QUEUE_SIZE;
5+
use libfuzzer_sys::fuzz_target;
6+
use std::hint::black_box;
7+
use virtio_blk::request::Request;
8+
use virtio_blk::stdio_executor::StdIoBackend;
9+
use virtio_queue::{mock::MockSplitQueue, Descriptor};
10+
use vm_memory::{Bytes, GuestAddress, GuestMemoryMmap};
11+
12+
fuzz_target!(|data: &[u8]| {
13+
let Ok(fuzz_input) = bincode::deserialize::<BlkInput>(data) else {
14+
return;
15+
};
16+
17+
let start_addr = GuestAddress(0x1000);
18+
// Create and randomly populate the guest memory
19+
let m = GuestMemoryMmap::<()>::from_ranges(&[(start_addr, 0x11000)]).unwrap();
20+
for (addr, mem) in fuzz_input.guestmem.iter() {
21+
let _ = m.write_slice(mem, GuestAddress(*addr));
22+
}
23+
24+
let vq = MockSplitQueue::create(&m, start_addr, DEFAULT_QUEUE_SIZE);
25+
26+
let descriptors: Vec<Descriptor> = fuzz_input
27+
.descriptors
28+
.iter()
29+
.map(|desc| (*desc).into())
30+
.collect();
31+
32+
// A backing in-memory file
33+
let memfile = memfd::MemfdOptions::default()
34+
.create("fuzzfile")
35+
.unwrap()
36+
.into_file();
37+
38+
// A backend that can execute a virtio-blk request
39+
let mut backend = StdIoBackend::new(memfile, fuzz_input.features).unwrap();
40+
if let Some(id) = fuzz_input.device_id {
41+
backend = backend.with_device_id(id);
42+
}
43+
44+
// Build a descriptor chain, parse and execute a request
45+
if let Ok(mut chain) = vq.build_desc_chain(&descriptors) {
46+
if let Ok(req) = Request::parse(&mut chain) {
47+
// Ensure the compiler does not optimize the request away
48+
let _ = black_box(backend.process_request(&m, &req));
49+
};
50+
}
51+
});

0 commit comments

Comments
 (0)