xref: /aosp_15_r20/external/crosvm/fuzz/fuzz_targets/block_fuzzer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(not(test))]
6*bb4ee6a4SAndroid Build Coastguard Worker #![no_main]
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Cursor;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Seek;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::io::SeekFrom;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
16*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_fuzz::fuzz_target;
17*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::base_features;
18*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::block::DiskOption;
19*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::BlockAsync;
20*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::Interrupt;
21*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::QueueConfig;
22*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::VirtioDevice;
23*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqLevelEvent;
24*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::ProtectionType;
25*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
26*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
27*bb4ee6a4SAndroid Build Coastguard Worker 
28*bb4ee6a4SAndroid Build Coastguard Worker const MEM_SIZE: u64 = 256 * 1024 * 1024;
29*bb4ee6a4SAndroid Build Coastguard Worker const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
30*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
31*bb4ee6a4SAndroid Build Coastguard Worker const CMD_SIZE: usize = 16; // Bytes in the command.
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker fuzz_target!(|bytes| {
34*bb4ee6a4SAndroid Build Coastguard Worker     let size_u64 = size_of::<u64>();
35*bb4ee6a4SAndroid Build Coastguard Worker     let mem = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker     // The fuzz data is interpreted as:
38*bb4ee6a4SAndroid Build Coastguard Worker     // starting index 8 bytes
39*bb4ee6a4SAndroid Build Coastguard Worker     // command location 8 bytes
40*bb4ee6a4SAndroid Build Coastguard Worker     // command 16 bytes
41*bb4ee6a4SAndroid Build Coastguard Worker     // descriptors circular buffer 16 bytes * 3
42*bb4ee6a4SAndroid Build Coastguard Worker     if bytes.len() < 4 * size_u64 {
43*bb4ee6a4SAndroid Build Coastguard Worker         // Need an index to start.
44*bb4ee6a4SAndroid Build Coastguard Worker         return;
45*bb4ee6a4SAndroid Build Coastguard Worker     }
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker     let mut data_image = Cursor::new(bytes);
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker     let first_index = read_u64(&mut data_image);
50*bb4ee6a4SAndroid Build Coastguard Worker     if first_index > MEM_SIZE / DESC_SIZE {
51*bb4ee6a4SAndroid Build Coastguard Worker         return;
52*bb4ee6a4SAndroid Build Coastguard Worker     }
53*bb4ee6a4SAndroid Build Coastguard Worker     let first_offset = first_index * DESC_SIZE;
54*bb4ee6a4SAndroid Build Coastguard Worker     if first_offset as usize + size_u64 > bytes.len() {
55*bb4ee6a4SAndroid Build Coastguard Worker         return;
56*bb4ee6a4SAndroid Build Coastguard Worker     }
57*bb4ee6a4SAndroid Build Coastguard Worker 
58*bb4ee6a4SAndroid Build Coastguard Worker     let command_addr = read_u64(&mut data_image);
59*bb4ee6a4SAndroid Build Coastguard Worker     if command_addr > MEM_SIZE - CMD_SIZE as u64 {
60*bb4ee6a4SAndroid Build Coastguard Worker         return;
61*bb4ee6a4SAndroid Build Coastguard Worker     }
62*bb4ee6a4SAndroid Build Coastguard Worker     if mem
63*bb4ee6a4SAndroid Build Coastguard Worker         .write_all_at_addr(
64*bb4ee6a4SAndroid Build Coastguard Worker             &bytes[2 * size_u64..(2 * size_u64) + CMD_SIZE],
65*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(command_addr),
66*bb4ee6a4SAndroid Build Coastguard Worker         )
67*bb4ee6a4SAndroid Build Coastguard Worker         .is_err()
68*bb4ee6a4SAndroid Build Coastguard Worker     {
69*bb4ee6a4SAndroid Build Coastguard Worker         return;
70*bb4ee6a4SAndroid Build Coastguard Worker     }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker     data_image.seek(SeekFrom::Start(first_offset)).unwrap();
73*bb4ee6a4SAndroid Build Coastguard Worker     let desc_table = read_u64(&mut data_image);
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker     if mem
76*bb4ee6a4SAndroid Build Coastguard Worker         .write_all_at_addr(&bytes[32..], GuestAddress(desc_table))
77*bb4ee6a4SAndroid Build Coastguard Worker         .is_err()
78*bb4ee6a4SAndroid Build Coastguard Worker     {
79*bb4ee6a4SAndroid Build Coastguard Worker         return;
80*bb4ee6a4SAndroid Build Coastguard Worker     }
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker     let interrupt = Interrupt::new(
83*bb4ee6a4SAndroid Build Coastguard Worker         IrqLevelEvent::new().unwrap(),
84*bb4ee6a4SAndroid Build Coastguard Worker         None,   // msix_config
85*bb4ee6a4SAndroid Build Coastguard Worker         0xFFFF, // VIRTIO_MSI_NO_VECTOR
86*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(target_arch = "x86_64")]
87*bb4ee6a4SAndroid Build Coastguard Worker         None,
88*bb4ee6a4SAndroid Build Coastguard Worker     );
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker     let mut q = QueueConfig::new(QUEUE_SIZE, 0);
91*bb4ee6a4SAndroid Build Coastguard Worker     q.set_size(QUEUE_SIZE / 2);
92*bb4ee6a4SAndroid Build Coastguard Worker     q.set_ready(true);
93*bb4ee6a4SAndroid Build Coastguard Worker     let q = q
94*bb4ee6a4SAndroid Build Coastguard Worker         .activate(&mem, Event::new().unwrap(), interrupt.clone())
95*bb4ee6a4SAndroid Build Coastguard Worker         .expect("QueueConfig::activate");
96*bb4ee6a4SAndroid Build Coastguard Worker     let queue_evt = q.event().try_clone().unwrap();
97*bb4ee6a4SAndroid Build Coastguard Worker 
98*bb4ee6a4SAndroid Build Coastguard Worker     let features = base_features(ProtectionType::Unprotected);
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker     let disk_file = tempfile::tempfile().unwrap();
101*bb4ee6a4SAndroid Build Coastguard Worker     let disk_option = DiskOption::default();
102*bb4ee6a4SAndroid Build Coastguard Worker     let mut block = BlockAsync::new(
103*bb4ee6a4SAndroid Build Coastguard Worker         features,
104*bb4ee6a4SAndroid Build Coastguard Worker         Box::new(disk_file),
105*bb4ee6a4SAndroid Build Coastguard Worker         &disk_option,
106*bb4ee6a4SAndroid Build Coastguard Worker         None,
107*bb4ee6a4SAndroid Build Coastguard Worker         None,
108*bb4ee6a4SAndroid Build Coastguard Worker         None,
109*bb4ee6a4SAndroid Build Coastguard Worker     )
110*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap();
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker     block
113*bb4ee6a4SAndroid Build Coastguard Worker         .activate(mem, interrupt, BTreeMap::from([(0, q)]))
114*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
115*bb4ee6a4SAndroid Build Coastguard Worker 
116*bb4ee6a4SAndroid Build Coastguard Worker     queue_evt.signal().unwrap(); // Rings the doorbell
117*bb4ee6a4SAndroid Build Coastguard Worker });
118*bb4ee6a4SAndroid Build Coastguard Worker 
read_u64<T: Read>(readable: &mut T) -> u64119*bb4ee6a4SAndroid Build Coastguard Worker fn read_u64<T: Read>(readable: &mut T) -> u64 {
120*bb4ee6a4SAndroid Build Coastguard Worker     let mut buf = [0u8; size_of::<u64>()];
121*bb4ee6a4SAndroid Build Coastguard Worker     readable.read_exact(&mut buf[..]).unwrap();
122*bb4ee6a4SAndroid Build Coastguard Worker     u64::from_le_bytes(buf)
123*bb4ee6a4SAndroid Build Coastguard Worker }
124