xref: /cloud-hypervisor/fuzz/fuzz_targets/serial.rs (revision eea9bcea38e0c5649f444c829f3a4f9c22aa486c)
1 // Copyright © 2022 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #![no_main]
6 use devices::legacy::Serial;
7 use libc::EFD_NONBLOCK;
8 use libfuzzer_sys::fuzz_target;
9 use std::sync::Arc;
10 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig, InterruptSourceGroup};
11 use vm_device::BusDevice;
12 use vmm_sys_util::eventfd::EventFd;
13 
14 fuzz_target!(|bytes| {
15     let mut serial = Serial::new_sink(
16         "serial".into(),
17         Arc::new(TestInterrupt::new(EventFd::new(EFD_NONBLOCK).unwrap())),
18     );
19 
20     let mut i = 0;
21     while i < bytes.len() {
22         let choice = bytes.get(i).unwrap_or(&0) % 3;
23         i += 1;
24 
25         match choice {
26             0 => {
27                 let offset = (bytes.get(i).unwrap_or(&0) % 8) as u64;
28                 i += 1;
29                 let mut out_bytes = vec![0];
30                 serial.read(0, offset, &mut out_bytes);
31             }
32             1 => {
33                 let offset = (bytes.get(i).unwrap_or(&0) % 8) as u64;
34                 i += 1;
35                 let data = vec![*bytes.get(i).unwrap_or(&0)];
36                 i += 1;
37                 serial.write(0, offset, &data);
38             }
39             _ => {
40                 let data = vec![*bytes.get(i).unwrap_or(&0)];
41                 i += 1;
42                 serial.queue_input_bytes(&data).ok();
43             }
44         }
45     }
46 });
47 
48 struct TestInterrupt {
49     event_fd: EventFd,
50 }
51 
52 impl InterruptSourceGroup for TestInterrupt {
53     fn trigger(&self, _index: InterruptIndex) -> Result<(), std::io::Error> {
54         self.event_fd.write(1)
55     }
56     fn update(
57         &self,
58         _index: InterruptIndex,
59         _config: InterruptSourceConfig,
60         _masked: bool,
61     ) -> Result<(), std::io::Error> {
62         Ok(())
63     }
64     fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
65         Some(self.event_fd.try_clone().unwrap())
66     }
67 }
68 
69 impl TestInterrupt {
70     fn new(event_fd: EventFd) -> Self {
71         TestInterrupt { event_fd }
72     }
73 }
74