1 // Copyright © 2022 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 #![no_main] 6 use libfuzzer_sys::fuzz_target; 7 use micro_http::Request; 8 use once_cell::sync::Lazy; 9 use std::os::unix::io::AsRawFd; 10 use std::sync::mpsc::{channel, Receiver}; 11 use std::thread; 12 use vmm::api::{http::*, ApiRequest, ApiResponsePayload}; 13 use vmm::{EpollContext, EpollDispatch}; 14 use vmm_sys_util::eventfd::EventFd; 15 16 // Need to be ordered for test case reproducibility 17 static ROUTES: Lazy<Vec<&Box<dyn EndpointHandler + Sync + Send>>> = 18 Lazy::new(|| HTTP_ROUTES.routes.values().collect()); 19 20 fuzz_target!(|bytes| { 21 if bytes.len() < 2 { 22 return; 23 } 24 25 let route = ROUTES[bytes[0] as usize % ROUTES.len()]; 26 if let Some(request) = generate_request(&bytes[1..]) { 27 let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); 28 let api_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); 29 let (api_sender, api_receiver) = channel(); 30 31 let http_receiver_thread = { 32 let exit_evt = exit_evt.try_clone().unwrap(); 33 let api_evt = api_evt.try_clone().unwrap(); 34 thread::Builder::new() 35 .name("http_receiver".to_string()) 36 .spawn(move || { 37 http_receiver_stub(exit_evt, api_evt, api_receiver); 38 }) 39 .unwrap() 40 }; 41 42 route.handle_request(&request, api_evt, api_sender); 43 exit_evt.write(1).ok(); 44 http_receiver_thread.join().unwrap(); 45 }; 46 }); 47 48 fn generate_request(bytes: &[u8]) -> Option<Request> { 49 let req_method = match bytes[0] % 5 { 50 0 => "GET", 51 1 => "PUT", 52 2 => "PATCH", 53 3 => "POST", 54 _ => "INVALID", 55 }; 56 let request_line = format!("{} http://localhost/home HTTP/1.1\r\n", req_method); 57 58 let req_body = &bytes[1..]; 59 let request = if req_body.len() > 0 { 60 [ 61 format!("{}Content-Length: {}\r\n", request_line, req_body.len()).as_bytes(), 62 req_body, 63 ] 64 .concat() 65 } else { 66 format!("{}\r\n", request_line).as_bytes().to_vec() 67 }; 68 69 Request::try_from(&request, None).ok() 70 } 71 72 fn http_receiver_stub(exit_evt: EventFd, api_evt: EventFd, api_receiver: Receiver<ApiRequest>) { 73 let mut epoll = EpollContext::new().unwrap(); 74 epoll.add_event(&exit_evt, EpollDispatch::Exit).unwrap(); 75 epoll.add_event(&api_evt, EpollDispatch::Api).unwrap(); 76 77 let epoll_fd = epoll.as_raw_fd(); 78 let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); 2]; 79 let num_events; 80 loop { 81 num_events = match epoll::wait(epoll_fd, -1, &mut events[..]) { 82 Ok(num_events) => num_events, 83 Err(e) => match e.raw_os_error() { 84 Some(libc::EAGAIN) | Some(libc::EINTR) => continue, 85 _ => panic!("Unexpected epoll::wait error!"), 86 }, 87 }; 88 89 break; 90 } 91 92 for event in events.iter().take(num_events) { 93 let dispatch_event: EpollDispatch = event.data.into(); 94 match dispatch_event { 95 EpollDispatch::Exit => { 96 break; 97 } 98 EpollDispatch::Api => { 99 for _ in 0..api_evt.read().unwrap() { 100 let api_request = api_receiver.recv().unwrap(); 101 match api_request { 102 ApiRequest::VmCreate(_, sender) => { 103 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 104 } 105 ApiRequest::VmDelete(sender) => { 106 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 107 } 108 ApiRequest::VmBoot(sender) => { 109 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 110 } 111 ApiRequest::VmShutdown(sender) => { 112 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 113 } 114 ApiRequest::VmReboot(sender) => { 115 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 116 } 117 ApiRequest::VmInfo(sender) => { 118 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 119 } 120 ApiRequest::VmmPing(sender) => { 121 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 122 } 123 ApiRequest::VmPause(sender) => { 124 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 125 } 126 ApiRequest::VmResume(sender) => { 127 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 128 } 129 ApiRequest::VmSnapshot(_, sender) => { 130 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 131 } 132 ApiRequest::VmRestore(_, sender) => { 133 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 134 } 135 ApiRequest::VmmShutdown(sender) => { 136 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 137 } 138 ApiRequest::VmResize(_, sender) => { 139 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 140 } 141 ApiRequest::VmResizeZone(_, sender) => { 142 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 143 } 144 ApiRequest::VmAddDevice(_, sender) => { 145 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 146 } 147 ApiRequest::VmAddUserDevice(_, sender) => { 148 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 149 } 150 ApiRequest::VmRemoveDevice(_, sender) => { 151 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 152 } 153 ApiRequest::VmAddDisk(_, sender) => { 154 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 155 } 156 ApiRequest::VmAddFs(_, sender) => { 157 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 158 } 159 ApiRequest::VmAddPmem(_, sender) => { 160 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 161 } 162 ApiRequest::VmAddNet(_, sender) => { 163 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 164 } 165 ApiRequest::VmAddVdpa(_, sender) => { 166 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 167 } 168 ApiRequest::VmAddVsock(_, sender) => { 169 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 170 } 171 ApiRequest::VmCounters(sender) => { 172 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 173 } 174 ApiRequest::VmReceiveMigration(_, sender) => { 175 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 176 } 177 ApiRequest::VmSendMigration(_, sender) => { 178 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 179 } 180 ApiRequest::VmPowerButton(sender) => { 181 sender.send(Ok(ApiResponsePayload::Empty)).unwrap(); 182 } 183 } 184 } 185 } 186 _ => { 187 panic!("Unexpected Epoll event"); 188 } 189 } 190 } 191 } 192