Skip to content

Commit

Permalink
fuzzing: initial fuzzing implementation
Browse files Browse the repository at this point in the history
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.

The fuzzing harnesses, much like regular tests, are built as userspace
binaries, which means we need to disable the SVSM allocator in favor
of the standard Rust allocator.

This works towards issue coconut-svsm#34.

Signed-off-by: Carlos López <[email protected]>
  • Loading branch information
00xc committed Oct 2, 2023
1 parent 7e356a9 commit 4bd6a64
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 2 deletions.
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
150 changes: 150 additions & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions fuzz/Cargo.toml
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
4 changes: 4 additions & 0 deletions fuzz/acpi-dict.txt
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"
65 changes: 65 additions & 0 deletions fuzz/fuzz_targets/acpi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2022-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
});
27 changes: 27 additions & 0 deletions fuzz/fuzz_targets/fw_meta.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2022-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
});
4 changes: 2 additions & 2 deletions src/mm/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1266,8 +1266,8 @@ unsafe impl GlobalAlloc for SvsmAllocator {
}
}

#[cfg_attr(not(any(test, doctest)), global_allocator)]
#[cfg_attr(any(test, doctest), allow(dead_code))]
#[cfg_attr(not(any(test, doctest, fuzzing)), global_allocator)]
#[cfg_attr(any(test, doctest, fuzzing), allow(dead_code))]
static mut ALLOCATOR: SvsmAllocator = SvsmAllocator::new();

pub fn root_mem_init(pstart: PhysAddr, vstart: VirtAddr, page_count: usize) {
Expand Down

0 comments on commit 4bd6a64

Please sign in to comment.