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