1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 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::io::Read; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of; 11*bb4ee6a4SAndroid Build Coastguard Worker 12*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 13*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_fuzz::fuzz_target; 14*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_fuzz::rand::FuzzRng; 15*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::Interrupt; 16*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::QueueConfig; 17*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqLevelEvent; 18*bb4ee6a4SAndroid Build Coastguard Worker use rand::Rng; 19*bb4ee6a4SAndroid Build Coastguard Worker use rand::RngCore; 20*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress; 21*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory; 22*bb4ee6a4SAndroid Build Coastguard Worker 23*bb4ee6a4SAndroid Build Coastguard Worker const MAX_QUEUE_SIZE: u16 = 256; 24*bb4ee6a4SAndroid Build Coastguard Worker const MEM_SIZE: u64 = 1024 * 1024; 25*bb4ee6a4SAndroid Build Coastguard Worker 26*bb4ee6a4SAndroid Build Coastguard Worker thread_local! { 27*bb4ee6a4SAndroid Build Coastguard Worker static GUEST_MEM: GuestMemory = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap(); 28*bb4ee6a4SAndroid Build Coastguard Worker } 29*bb4ee6a4SAndroid Build Coastguard Worker 30*bb4ee6a4SAndroid Build Coastguard Worker // These are taken from the virtio spec and can be used as a reference for the size calculations in 31*bb4ee6a4SAndroid Build Coastguard Worker // the fuzzer. 32*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)] 33*bb4ee6a4SAndroid Build Coastguard Worker struct virtq_desc { 34*bb4ee6a4SAndroid Build Coastguard Worker addr: u64, 35*bb4ee6a4SAndroid Build Coastguard Worker len: u32, 36*bb4ee6a4SAndroid Build Coastguard Worker flags: u16, 37*bb4ee6a4SAndroid Build Coastguard Worker next: u16, 38*bb4ee6a4SAndroid Build Coastguard Worker } 39*bb4ee6a4SAndroid Build Coastguard Worker 40*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)] 41*bb4ee6a4SAndroid Build Coastguard Worker struct virtq_avail { 42*bb4ee6a4SAndroid Build Coastguard Worker flags: u16, 43*bb4ee6a4SAndroid Build Coastguard Worker idx: u16, 44*bb4ee6a4SAndroid Build Coastguard Worker ring: [u16; MAX_QUEUE_SIZE as usize], 45*bb4ee6a4SAndroid Build Coastguard Worker used_event: u16, 46*bb4ee6a4SAndroid Build Coastguard Worker } 47*bb4ee6a4SAndroid Build Coastguard Worker 48*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)] 49*bb4ee6a4SAndroid Build Coastguard Worker struct virtq_used_elem { 50*bb4ee6a4SAndroid Build Coastguard Worker id: u32, 51*bb4ee6a4SAndroid Build Coastguard Worker len: u32, 52*bb4ee6a4SAndroid Build Coastguard Worker } 53*bb4ee6a4SAndroid Build Coastguard Worker 54*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)] 55*bb4ee6a4SAndroid Build Coastguard Worker struct virtq_used { 56*bb4ee6a4SAndroid Build Coastguard Worker flags: u16, 57*bb4ee6a4SAndroid Build Coastguard Worker idx: u16, 58*bb4ee6a4SAndroid Build Coastguard Worker ring: [virtq_used_elem; MAX_QUEUE_SIZE as usize], 59*bb4ee6a4SAndroid Build Coastguard Worker avail_event: u16, 60*bb4ee6a4SAndroid Build Coastguard Worker } 61*bb4ee6a4SAndroid Build Coastguard Worker 62*bb4ee6a4SAndroid Build Coastguard Worker fuzz_target!(|data: &[u8]| { 63*bb4ee6a4SAndroid Build Coastguard Worker let interrupt = Interrupt::new( 64*bb4ee6a4SAndroid Build Coastguard Worker IrqLevelEvent::new().unwrap(), 65*bb4ee6a4SAndroid Build Coastguard Worker None, // msix_config 66*bb4ee6a4SAndroid Build Coastguard Worker 0xFFFF, // VIRTIO_MSI_NO_VECTOR 67*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 68*bb4ee6a4SAndroid Build Coastguard Worker None, 69*bb4ee6a4SAndroid Build Coastguard Worker ); 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker let mut q = QueueConfig::new(MAX_QUEUE_SIZE, 0); 72*bb4ee6a4SAndroid Build Coastguard Worker let mut rng = FuzzRng::new(data); 73*bb4ee6a4SAndroid Build Coastguard Worker q.set_size(rng.gen()); 74*bb4ee6a4SAndroid Build Coastguard Worker 75*bb4ee6a4SAndroid Build Coastguard Worker // For each of {desc_table,avail_ring,used_ring} generate a random address that includes enough 76*bb4ee6a4SAndroid Build Coastguard Worker // space to hold the relevant struct with the largest possible queue size. 77*bb4ee6a4SAndroid Build Coastguard Worker let max_table_size = MAX_QUEUE_SIZE as u64 * size_of::<virtq_desc>() as u64; 78*bb4ee6a4SAndroid Build Coastguard Worker q.set_desc_table(GuestAddress(rng.gen_range(0..MEM_SIZE - max_table_size))); 79*bb4ee6a4SAndroid Build Coastguard Worker q.set_avail_ring(GuestAddress( 80*bb4ee6a4SAndroid Build Coastguard Worker rng.gen_range(0..MEM_SIZE - size_of::<virtq_avail>() as u64), 81*bb4ee6a4SAndroid Build Coastguard Worker )); 82*bb4ee6a4SAndroid Build Coastguard Worker q.set_used_ring(GuestAddress( 83*bb4ee6a4SAndroid Build Coastguard Worker rng.gen_range(0..MEM_SIZE - size_of::<virtq_used>() as u64), 84*bb4ee6a4SAndroid Build Coastguard Worker )); 85*bb4ee6a4SAndroid Build Coastguard Worker q.set_ready(true); 86*bb4ee6a4SAndroid Build Coastguard Worker 87*bb4ee6a4SAndroid Build Coastguard Worker GUEST_MEM.with(|mem| { 88*bb4ee6a4SAndroid Build Coastguard Worker let mut q = if let Ok(q) = q.activate(mem, Event::new().unwrap(), interrupt) { 89*bb4ee6a4SAndroid Build Coastguard Worker q 90*bb4ee6a4SAndroid Build Coastguard Worker } else { 91*bb4ee6a4SAndroid Build Coastguard Worker return; 92*bb4ee6a4SAndroid Build Coastguard Worker }; 93*bb4ee6a4SAndroid Build Coastguard Worker 94*bb4ee6a4SAndroid Build Coastguard Worker // First zero out all of the memory. 95*bb4ee6a4SAndroid Build Coastguard Worker let vs = mem 96*bb4ee6a4SAndroid Build Coastguard Worker .get_slice_at_addr(GuestAddress(0), MEM_SIZE as usize) 97*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 98*bb4ee6a4SAndroid Build Coastguard Worker vs.write_bytes(0); 99*bb4ee6a4SAndroid Build Coastguard Worker 100*bb4ee6a4SAndroid Build Coastguard Worker // Fill in the descriptor table. 101*bb4ee6a4SAndroid Build Coastguard Worker let queue_size = q.size() as usize; 102*bb4ee6a4SAndroid Build Coastguard Worker let mut buf = vec![0u8; queue_size * size_of::<virtq_desc>()]; 103*bb4ee6a4SAndroid Build Coastguard Worker 104*bb4ee6a4SAndroid Build Coastguard Worker rng.fill_bytes(&mut buf[..]); 105*bb4ee6a4SAndroid Build Coastguard Worker mem.write_all_at_addr(&buf[..], q.desc_table()).unwrap(); 106*bb4ee6a4SAndroid Build Coastguard Worker 107*bb4ee6a4SAndroid Build Coastguard Worker // Fill in the available ring. See the definition of virtq_avail above for the source of 108*bb4ee6a4SAndroid Build Coastguard Worker // these numbers. 109*bb4ee6a4SAndroid Build Coastguard Worker let avail_size = 4 + (queue_size * 2) + 2; 110*bb4ee6a4SAndroid Build Coastguard Worker buf.resize(avail_size, 0); 111*bb4ee6a4SAndroid Build Coastguard Worker rng.fill_bytes(&mut buf[..]); 112*bb4ee6a4SAndroid Build Coastguard Worker mem.write_all_at_addr(&buf[..], q.avail_ring()).unwrap(); 113*bb4ee6a4SAndroid Build Coastguard Worker 114*bb4ee6a4SAndroid Build Coastguard Worker // Fill in the used ring. See the definition of virtq_used above for the source of 115*bb4ee6a4SAndroid Build Coastguard Worker // these numbers. 116*bb4ee6a4SAndroid Build Coastguard Worker let used_size = 4 + (queue_size * size_of::<virtq_used_elem>()) + 2; 117*bb4ee6a4SAndroid Build Coastguard Worker buf.resize(used_size, 0); 118*bb4ee6a4SAndroid Build Coastguard Worker rng.fill_bytes(&mut buf[..]); 119*bb4ee6a4SAndroid Build Coastguard Worker mem.write_all_at_addr(&buf[..], q.used_ring()).unwrap(); 120*bb4ee6a4SAndroid Build Coastguard Worker 121*bb4ee6a4SAndroid Build Coastguard Worker while let Some(mut avail_desc) = q.pop() { 122*bb4ee6a4SAndroid Build Coastguard Worker // Read the entire readable portion of the buffer. 123*bb4ee6a4SAndroid Build Coastguard Worker let mut read_buf = vec![0u8; avail_desc.reader.available_bytes()]; 124*bb4ee6a4SAndroid Build Coastguard Worker avail_desc.reader.read_exact(&mut read_buf).unwrap(); 125*bb4ee6a4SAndroid Build Coastguard Worker 126*bb4ee6a4SAndroid Build Coastguard Worker // Write the entire writable portion of the buffer. 127*bb4ee6a4SAndroid Build Coastguard Worker let write_buf = vec![0u8; avail_desc.writer.available_bytes()]; 128*bb4ee6a4SAndroid Build Coastguard Worker avail_desc.writer.write_all(&write_buf).unwrap(); 129*bb4ee6a4SAndroid Build Coastguard Worker 130*bb4ee6a4SAndroid Build Coastguard Worker let bytes_written = avail_desc.writer.bytes_written() as u32; 131*bb4ee6a4SAndroid Build Coastguard Worker q.add_used(avail_desc, bytes_written); 132*bb4ee6a4SAndroid Build Coastguard Worker } 133*bb4ee6a4SAndroid Build Coastguard Worker }); 134*bb4ee6a4SAndroid Build Coastguard Worker }); 135