xref: /cloud-hypervisor/fuzz/fuzz_targets/serial.rs (revision 6f8bd27cf7629733582d930519e98d19e90afb16)
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         None,
19     );
20 
21     let mut i = 0;
22     while i < bytes.len() {
23         let choice = bytes.get(i).unwrap_or(&0) % 3;
24         i += 1;
25 
26         match choice {
27             0 => {
28                 let offset = (bytes.get(i).unwrap_or(&0) % 8) as u64;
29                 i += 1;
30                 let mut out_bytes = vec![0];
31                 serial.read(0, offset, &mut out_bytes);
32             }
33             1 => {
34                 let offset = (bytes.get(i).unwrap_or(&0) % 8) as u64;
35                 i += 1;
36                 let data = vec![*bytes.get(i).unwrap_or(&0)];
37                 i += 1;
38                 serial.write(0, offset, &data);
39             }
40             _ => {
41                 let data = vec![*bytes.get(i).unwrap_or(&0)];
42                 i += 1;
43                 serial.queue_input_bytes(&data).ok();
44             }
45         }
46     }
47 });
48 
49 struct TestInterrupt {
50     event_fd: EventFd,
51 }
52 
53 impl InterruptSourceGroup for TestInterrupt {
54     fn trigger(&self, _index: InterruptIndex) -> Result<(), std::io::Error> {
55         self.event_fd.write(1)
56     }
57     fn update(
58         &self,
59         _index: InterruptIndex,
60         _config: InterruptSourceConfig,
61         _masked: bool,
62     ) -> Result<(), std::io::Error> {
63         Ok(())
64     }
65     fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
66         Some(self.event_fd.try_clone().unwrap())
67     }
68 }
69 
70 impl TestInterrupt {
71     fn new(event_fd: EventFd) -> Self {
72         TestInterrupt { event_fd }
73     }
74 }
75