From 5ba3b80e83145caafa5be8ed844a7f27e574e271 Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Wed, 3 Aug 2022 18:30:06 -0700 Subject: [PATCH] fuzz: block: Ensure a queue event is properly processed Currently the main thread returns immediately after sending a 'queue' event which is rarely received and processed by the virtio-block thread (unless system is in high workload). In this way, the fuzzer is mostly doing nothing and is unable to reproduce its behavior deterministically (from the same inputs). This patch relies on a 'level-triggered' epoll to ensure a 'queue' event is properly processed before return from the main thread. Signed-off-by: Bo Chen --- fuzz/fuzz_targets/block.rs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/fuzz/fuzz_targets/block.rs b/fuzz/fuzz_targets/block.rs index 8c190f3c5..5df66fdd0 100644 --- a/fuzz/fuzz_targets/block.rs +++ b/fuzz/fuzz_targets/block.rs @@ -17,6 +17,7 @@ use std::sync::Arc; use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType}; use virtio_queue::{Queue, QueueT}; use vm_memory::{bitmap::AtomicBitmap, Bytes, GuestAddress, GuestMemoryAtomic}; +use vmm::{EpollContext, EpollDispatch}; use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK}; type GuestMemoryMmap = vm_memory::GuestMemoryMmap; @@ -111,6 +112,8 @@ fuzz_target!(|bytes| { .ok(); queue_evt.write(77).unwrap(); // Rings the doorbell, any byte will do. + + wait_queue_event_processed(queue_evt); }); fn read_u64(readable: &mut T) -> u64 { @@ -132,10 +135,33 @@ fn memfd_create(name: &ffi::CStr, flags: u32) -> Result { pub struct NoopVirtioInterrupt {} impl VirtioInterrupt for NoopVirtioInterrupt { - fn trigger( - &self, - _int_type: VirtioInterruptType, - ) -> std::result::Result<(), std::io::Error> { + fn trigger(&self, _int_type: VirtioInterruptType) -> std::result::Result<(), std::io::Error> { Ok(()) } } + +fn wait_queue_event_processed(queue_evt: EventFd) { + let mut epoll = EpollContext::new().unwrap(); + epoll.add_event(&queue_evt, EpollDispatch::Api).unwrap(); + + let epoll_fd = epoll.as_raw_fd(); + let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); 1]; + + loop { + let num_events = match epoll::wait(epoll_fd, 0, &mut events[..]) { + Ok(res) => res, + Err(e) => { + if e.kind() == io::ErrorKind::Interrupted { + continue; + } + + println!("Warning: Unexpected epoll::wait() error!"); + break; + } + }; + + if num_events == 0 { + break; + } + } +}