1 // Copyright © 2025 Microsoft Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 #![no_main]
6
7 use hypervisor::arch::emulator::{PlatformEmulator, PlatformError};
8 use hypervisor::arch::x86::emulator::{Emulator, EmulatorCpuState};
9 use hypervisor::arch::x86::{DescriptorTable, SegmentRegister, SpecialRegisters};
10 use hypervisor::StandardRegisters;
11 use libfuzzer_sys::{fuzz_target, Corpus};
12
13 #[derive(Debug)]
14 struct EmulatorContext {
15 state: EmulatorCpuState,
16 memory: [u8; 8],
17 }
18
19 impl PlatformEmulator for EmulatorContext {
20 type CpuState = EmulatorCpuState;
21
read_memory(&self, _gva: u64, data: &mut [u8]) -> Result<(), PlatformError>22 fn read_memory(&self, _gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
23 data.copy_from_slice(&self.memory[..data.len()]);
24 Ok(())
25 }
26
write_memory(&mut self, _gva: u64, _data: &[u8]) -> Result<(), PlatformError>27 fn write_memory(&mut self, _gva: u64, _data: &[u8]) -> Result<(), PlatformError> {
28 // Discard writes
29 Ok(())
30 }
31
cpu_state(&self, _cpu_id: usize) -> Result<Self::CpuState, PlatformError>32 fn cpu_state(&self, _cpu_id: usize) -> Result<Self::CpuState, PlatformError> {
33 Ok(self.state.clone())
34 }
35
set_cpu_state(&self, _cpu_id: usize, _state: Self::CpuState) -> Result<(), PlatformError>36 fn set_cpu_state(&self, _cpu_id: usize, _state: Self::CpuState) -> Result<(), PlatformError> {
37 // Ignore
38 Ok(())
39 }
40
fetch(&self, _ip: u64, _data: &mut [u8]) -> Result<(), PlatformError>41 fn fetch(&self, _ip: u64, _data: &mut [u8]) -> Result<(), PlatformError> {
42 // The fuzzer already provides 16 bytes of data, we don't need to fetch anything
43 panic!("fetch should not be called");
44 }
45 }
46
47 fuzz_target!(|bytes: &[u8]| -> Corpus {
48 let (mut ctx, insn) = match generate_context_and_instruction(bytes) {
49 Ok((ctx, insn)) => (ctx, insn),
50 Err(_) => return Corpus::Reject,
51 };
52
53 let mut e = Emulator::new(&mut ctx);
54
55 if e.emulate_first_insn(0, &insn).is_err() {
56 return Corpus::Reject;
57 }
58
59 Corpus::Keep
60 });
61
62 // Helper functions to generate structures from fuzzer input below
63
generate_segment_register( u: &mut arbitrary::Unstructured<'_>, ) -> arbitrary::Result<SegmentRegister>64 fn generate_segment_register(
65 u: &mut arbitrary::Unstructured<'_>,
66 ) -> arbitrary::Result<SegmentRegister> {
67 Ok(SegmentRegister {
68 base: u.arbitrary()?,
69 limit: u.arbitrary()?,
70 selector: u.arbitrary()?,
71 avl: u.arbitrary()?,
72 dpl: u.arbitrary()?,
73 db: u.arbitrary()?,
74 g: u.arbitrary()?,
75 l: u.arbitrary()?,
76 present: u.arbitrary()?,
77 s: u.arbitrary()?,
78 type_: u.arbitrary()?,
79 unusable: u.arbitrary()?,
80 })
81 }
82
generate_descriptor_table( u: &mut arbitrary::Unstructured<'_>, ) -> arbitrary::Result<DescriptorTable>83 fn generate_descriptor_table(
84 u: &mut arbitrary::Unstructured<'_>,
85 ) -> arbitrary::Result<DescriptorTable> {
86 Ok(DescriptorTable {
87 base: u.arbitrary()?,
88 limit: u.arbitrary()?,
89 })
90 }
91
generate_context_and_instruction( bytes: &[u8], ) -> arbitrary::Result<(EmulatorContext, [u8; 16])>92 fn generate_context_and_instruction(
93 bytes: &[u8],
94 ) -> arbitrary::Result<(EmulatorContext, [u8; 16])> {
95 let mut u = arbitrary::Unstructured::new(bytes);
96
97 let mut regs = mshv_bindings::StandardRegisters {
98 rax: u.arbitrary()?,
99 rbx: u.arbitrary()?,
100 rcx: u.arbitrary()?,
101 rdx: u.arbitrary()?,
102 rsi: u.arbitrary()?,
103 rdi: u.arbitrary()?,
104 rsp: u.arbitrary()?,
105 rbp: u.arbitrary()?,
106 r8: u.arbitrary()?,
107 r9: u.arbitrary()?,
108 r10: u.arbitrary()?,
109 r11: u.arbitrary()?,
110 r12: u.arbitrary()?,
111 r13: u.arbitrary()?,
112 r14: u.arbitrary()?,
113 r15: u.arbitrary()?,
114 rip: u.arbitrary()?,
115 rflags: u.arbitrary()?,
116 };
117
118 // Cap RCX to avoid looping for too long for reps instructions.
119 regs.rcx &= 0xFFFFu64;
120
121 let regs = StandardRegisters::Mshv(regs);
122
123 let sregs = SpecialRegisters {
124 cs: generate_segment_register(&mut u)?,
125 ds: generate_segment_register(&mut u)?,
126 es: generate_segment_register(&mut u)?,
127 fs: generate_segment_register(&mut u)?,
128 gs: generate_segment_register(&mut u)?,
129 ss: generate_segment_register(&mut u)?,
130 tr: generate_segment_register(&mut u)?,
131 ldt: generate_segment_register(&mut u)?,
132 gdt: generate_descriptor_table(&mut u)?,
133 idt: generate_descriptor_table(&mut u)?,
134 cr0: u.arbitrary()?,
135 cr2: u.arbitrary()?,
136 cr3: u.arbitrary()?,
137 cr4: u.arbitrary()?,
138 cr8: u.arbitrary()?,
139 efer: u.arbitrary()?,
140 apic_base: u.arbitrary()?,
141 interrupt_bitmap: u.arbitrary()?,
142 };
143
144 let memory = u.arbitrary::<[u8; 8]>()?;
145 let insn = u.arbitrary::<[u8; 16]>()?;
146
147 let ctx = EmulatorContext {
148 state: EmulatorCpuState { regs, sregs },
149 memory,
150 };
151
152 Ok((ctx, insn))
153 }
154