mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
Allow the user to specify a serial number for each virtio block device using the new id= parameter: crosvm run --disk disk.img,id=SERIALNO ... These serial numbers show up in sysfs for each block device, which allows them to be uniquely identified regardless of the number or order of block devices added on the crosvm command line. This can be used to find a specific device by serial number for mounting at boot time. BUG=b:157687637 BUG=chromium:775781 TEST=crosvm run -r vm_rootfs.img,id=root -p init=/bin/bash vm_kernel TEST=cat /sys/block/vda/serial # see serial is set to "root" TEST=cargo test -p devices Change-Id: I108cdc47c367fb038d6acd55da60f9e1aae59e68 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2225559 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Chirantan Ekbote <chirantan@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
106 lines
2.9 KiB
Rust
106 lines
2.9 KiB
Rust
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#![no_main]
|
|
|
|
use std::io::{Cursor, Read, Seek, SeekFrom};
|
|
use std::mem::size_of;
|
|
use std::sync::atomic::AtomicUsize;
|
|
use std::sync::Arc;
|
|
|
|
use base::Event;
|
|
use cros_fuzz::fuzz_target;
|
|
use devices::virtio::{base_features, Block, Interrupt, Queue, VirtioDevice};
|
|
use tempfile;
|
|
use vm_memory::{GuestAddress, GuestMemory};
|
|
|
|
const MEM_SIZE: u64 = 256 * 1024 * 1024;
|
|
const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
|
|
const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
|
|
const CMD_SIZE: usize = 16; // Bytes in the command.
|
|
|
|
fuzz_target!(|bytes| {
|
|
let size_u64 = size_of::<u64>();
|
|
let mem = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
|
|
|
|
// The fuzz data is interpreted as:
|
|
// starting index 8 bytes
|
|
// command location 8 bytes
|
|
// command 16 bytes
|
|
// descriptors circular buffer 16 bytes * 3
|
|
if bytes.len() < 4 * size_u64 {
|
|
// Need an index to start.
|
|
return;
|
|
}
|
|
|
|
let mut data_image = Cursor::new(bytes);
|
|
|
|
let first_index = read_u64(&mut data_image);
|
|
if first_index > MEM_SIZE / DESC_SIZE {
|
|
return;
|
|
}
|
|
let first_offset = first_index * DESC_SIZE;
|
|
if first_offset as usize + size_u64 > bytes.len() {
|
|
return;
|
|
}
|
|
|
|
let command_addr = read_u64(&mut data_image);
|
|
if command_addr > MEM_SIZE - CMD_SIZE as u64 {
|
|
return;
|
|
}
|
|
if mem
|
|
.write_all_at_addr(
|
|
&bytes[2 * size_u64..(2 * size_u64) + CMD_SIZE],
|
|
GuestAddress(command_addr as u64),
|
|
)
|
|
.is_err()
|
|
{
|
|
return;
|
|
}
|
|
|
|
data_image.seek(SeekFrom::Start(first_offset)).unwrap();
|
|
let desc_table = read_u64(&mut data_image);
|
|
|
|
if mem
|
|
.write_all_at_addr(&bytes[32..], GuestAddress(desc_table as u64))
|
|
.is_err()
|
|
{
|
|
return;
|
|
}
|
|
|
|
let mut q = Queue::new(QUEUE_SIZE);
|
|
q.ready = true;
|
|
q.size = QUEUE_SIZE / 2;
|
|
q.max_size = QUEUE_SIZE;
|
|
|
|
let queue_evts: Vec<Event> = vec![Event::new().unwrap()];
|
|
let queue_evt = queue_evts[0].try_clone().unwrap();
|
|
|
|
let features = base_features(false);
|
|
|
|
let disk_file = tempfile::tempfile().unwrap();
|
|
let mut block =
|
|
Block::new(features, Box::new(disk_file), false, true, 512, None, None).unwrap();
|
|
|
|
block.activate(
|
|
mem,
|
|
Interrupt::new(
|
|
Arc::new(AtomicUsize::new(0)),
|
|
Event::new().unwrap(),
|
|
Event::new().unwrap(),
|
|
None, // msix_config
|
|
0xFFFF, // VIRTIO_MSI_NO_VECTOR
|
|
),
|
|
vec![q],
|
|
queue_evts,
|
|
);
|
|
|
|
queue_evt.write(77).unwrap(); // Rings the doorbell, any byte will do.
|
|
});
|
|
|
|
fn read_u64<T: Read>(readable: &mut T) -> u64 {
|
|
let mut buf = [0u8; size_of::<u64>()];
|
|
readable.read_exact(&mut buf[..]).unwrap();
|
|
u64::from_le_bytes(buf)
|
|
}
|