From a00d29867c46693e68006058b532add82f0944fb Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Sat, 5 Aug 2023 09:43:12 +0100 Subject: [PATCH] fuzz, vmm: Avoid infinite loop in CMOS fuzzer With the addition of the spinning waiting for the exit event to be received in the CMOS device a regression was introduced into the CMOS fuzzer. Since there is nothing to receive the event in the fuzzer and there is nothing to update the bit the that the device is looping on; introducing an infinite loop. Use an Option<> type so that when running the device in the fuzzer no Arc is provided effectively disabling the spinning logic. Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61165 Signed-off-by: Rob Bradford --- devices/src/legacy/cmos.rs | 18 ++++++++++-------- fuzz/fuzz_targets/cmos.rs | 2 +- vmm/src/device_manager.rs | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/devices/src/legacy/cmos.rs b/devices/src/legacy/cmos.rs index 4ca331356..a04331546 100644 --- a/devices/src/legacy/cmos.rs +++ b/devices/src/legacy/cmos.rs @@ -25,7 +25,7 @@ pub struct Cmos { index: u8, data: [u8; DATA_LEN], reset_evt: EventFd, - vcpus_kill_signalled: Arc, + vcpus_kill_signalled: Option>, } impl Cmos { @@ -36,7 +36,7 @@ impl Cmos { mem_below_4g: u64, mem_above_4g: u64, reset_evt: EventFd, - vcpus_kill_signalled: Arc, + vcpus_kill_signalled: Option>, ) -> Cmos { let mut data = [0u8; DATA_LEN]; @@ -76,12 +76,14 @@ impl BusDevice for Cmos { if self.index == 0x8f && data[0] == 0 { info!("CMOS reset"); self.reset_evt.write(1).unwrap(); - // Spin until we are sure the reset_evt has been handled and that when - // we return from the KVM_RUN we will exit rather than re-enter the guest. - while !self.vcpus_kill_signalled.load(Ordering::SeqCst) { - // This is more effective than thread::yield_now() at - // avoiding a priority inversion with the VMM thread - thread::sleep(std::time::Duration::from_millis(1)); + if let Some(vcpus_kill_signalled) = self.vcpus_kill_signalled.take() { + // Spin until we are sure the reset_evt has been handled and that when + // we return from the KVM_RUN we will exit rather than re-enter the guest. + while !vcpus_kill_signalled.load(Ordering::SeqCst) { + // This is more effective than thread::yield_now() at + // avoiding a priority inversion with the VMM thread + thread::sleep(std::time::Duration::from_millis(1)); + } } } else { self.data[(self.index & INDEX_MASK) as usize] = data[0] diff --git a/fuzz/fuzz_targets/cmos.rs b/fuzz/fuzz_targets/cmos.rs index fba49db11..5b66eaaa1 100644 --- a/fuzz/fuzz_targets/cmos.rs +++ b/fuzz/fuzz_targets/cmos.rs @@ -27,7 +27,7 @@ fuzz_target!(|bytes| { u64::from_le_bytes(below_4g), u64::from_le_bytes(above_4g), EventFd::new(EFD_NONBLOCK).unwrap(), - Arc::new(AtomicBool::default()), + None, ); let mut i = 16; diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 038d65838..8c3f58c63 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1630,7 +1630,7 @@ impl DeviceManager { mem_below_4g, mem_above_4g, reset_evt, - vcpus_kill_signalled, + Some(vcpus_kill_signalled), ))); self.bus_devices