forked from coconut-svsm/svsm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fuzzing: initial fuzzing implementation
Add fuzzing to the COCONUT SVSM project via cargo-fuzz. This commit adds the base infrastructure for fuzzing, as well as two harnesses for testing the fw_meta and ACPI table interfaces respectively. This works towards issue coconut-svsm#34. Signed-off-by: Carlos López <[email protected]>
- Loading branch information
Showing
9 changed files
with
295 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
target | ||
corpus | ||
artifacts | ||
coverage |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[package] | ||
name = "svsm-fuzz" | ||
version = "0.0.0" | ||
publish = false | ||
edition = "2021" | ||
|
||
[package.metadata] | ||
cargo-fuzz = true | ||
|
||
[dependencies] | ||
libfuzzer-sys = "0.4" | ||
|
||
[dependencies.svsm] | ||
path = ".." | ||
|
||
# Prevent this from interfering with workspaces | ||
[workspace] | ||
members = ["."] | ||
|
||
[profile.release] | ||
debug = 1 | ||
|
||
[[bin]] | ||
name = "fw_meta" | ||
path = "fuzz_targets/fw_meta.rs" | ||
test = false | ||
doc = false | ||
|
||
[[bin]] | ||
name = "acpi" | ||
path = "fuzz_targets/acpi.rs" | ||
test = false | ||
doc = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"etc/acpi/rsdp" | ||
"etc/acpi/tables" | ||
"APIC" | ||
"\x00\x00\x00\x14" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
// | ||
// Copyright (c) 2023 SUSE LLC | ||
// | ||
// Author: Carlos López <[email protected]> | ||
|
||
#![no_main] | ||
|
||
use core::num::NonZeroUsize; | ||
use libfuzzer_sys::{fuzz_target, Corpus}; | ||
use std::cell::Cell; | ||
use std::hint::black_box; | ||
use svsm::acpi::tables::load_acpi_cpu_info; | ||
use svsm::fw_cfg::FwCfg; | ||
use svsm::io::IOPort; | ||
|
||
/// A structure that emulates port I/O from a libfuzzer input. | ||
#[derive(Clone, Debug)] | ||
struct FuzzIo<'a> { | ||
data: &'a [u8], | ||
len: NonZeroUsize, | ||
pos: Cell<usize>, | ||
} | ||
|
||
impl<'a> FuzzIo<'a> { | ||
/// Create a new [`FuzzIo`] instance. Returns [`None`] if the input is | ||
/// empty. | ||
fn new(data: &'a [u8]) -> Option<Self> { | ||
let len = NonZeroUsize::new(data.len())?; | ||
let pos = Cell::new(0); | ||
Some(Self { data, len, pos }) | ||
} | ||
} | ||
|
||
impl IOPort for FuzzIo<'_> { | ||
fn outb(&self, _port: u16, _value: u8) {} | ||
fn outw(&self, _port: u16, _value: u16) {} | ||
|
||
fn inb(&self, _port: u16) -> u8 { | ||
let pos = self.pos.get(); | ||
let val = unsafe { *self.data.get_unchecked(pos) }; | ||
self.pos.set((pos + 1) % self.len); | ||
val | ||
} | ||
|
||
fn inw(&self, port: u16) -> u16 { | ||
let mut buf = [0u8; 2]; | ||
buf[0] = self.inb(port); | ||
buf[1] = self.inb(port); | ||
u16::from_le_bytes(buf) | ||
} | ||
} | ||
|
||
fuzz_target!(|data: &[u8]| -> Corpus { | ||
let Some(io) = FuzzIo::new(data) else { | ||
return Corpus::Reject; | ||
}; | ||
let fwcfg = FwCfg::new(&io); | ||
|
||
if let Ok(info) = load_acpi_cpu_info(&fwcfg) { | ||
let _ = black_box(info); | ||
} | ||
|
||
Corpus::Keep | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
// | ||
// Copyright (c) 2023 SUSE LLC | ||
// | ||
// Author: Carlos López <[email protected]> | ||
|
||
#![no_main] | ||
|
||
use libfuzzer_sys::{fuzz_target, Corpus}; | ||
use std::hint::black_box; | ||
use svsm::address::VirtAddr; | ||
use svsm::fw_meta::parse_fw_meta_data; | ||
use svsm::types::PAGE_SIZE; | ||
|
||
fuzz_target!(|data: &[u8]| -> Corpus { | ||
if data.len() != PAGE_SIZE { | ||
return Corpus::Reject; | ||
} | ||
|
||
let addr = VirtAddr::from(data.as_ptr()); | ||
let fw_meta = parse_fw_meta_data(addr); | ||
if let Ok(meta) = fw_meta { | ||
let _ = black_box(meta); | ||
} | ||
|
||
Corpus::Keep | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
// | ||
// Author: Joerg Roedel <[email protected]> | ||
|
||
#[cfg(test)] | ||
#[cfg(any(test, fuzzing))] | ||
use crate::address::Address; | ||
use crate::address::{PhysAddr, VirtAddr}; | ||
use crate::utils::immut_after_init::ImmutAfterInitCell; | ||
|
@@ -30,7 +30,7 @@ pub fn init_kernel_mapping_info(vstart: VirtAddr, vend: VirtAddr, pstart: PhysAd | |
.expect("Already initialized kernel mapping info"); | ||
} | ||
|
||
#[cfg(not(test))] | ||
#[cfg(not(any(test, fuzzing)))] | ||
pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { | ||
if vaddr < KERNEL_MAPPING.virt_start || vaddr >= KERNEL_MAPPING.virt_end { | ||
panic!("Invalid physical address {:#018x}", vaddr); | ||
|
@@ -41,7 +41,7 @@ pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { | |
KERNEL_MAPPING.phys_start + offset | ||
} | ||
|
||
#[cfg(not(test))] | ||
#[cfg(not(any(test, fuzzing)))] | ||
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { | ||
let size: usize = KERNEL_MAPPING.virt_end - KERNEL_MAPPING.virt_start; | ||
if paddr < KERNEL_MAPPING.phys_start || paddr >= KERNEL_MAPPING.phys_start + size { | ||
|
@@ -53,12 +53,12 @@ pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { | |
KERNEL_MAPPING.virt_start + offset | ||
} | ||
|
||
#[cfg(test)] | ||
#[cfg(any(test, fuzzing))] | ||
pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { | ||
PhysAddr::from(vaddr.bits()) | ||
} | ||
|
||
#[cfg(test)] | ||
#[cfg(any(test, fuzzing))] | ||
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { | ||
VirtAddr::from(paddr.bits()) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters