Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ path = "fuzz_targets/kernel_params.rs"
test = false
doc = false
bench = false

# /proc/filesystems content parsing fuzz target
[[bin]]
name = "mount_parsing"
path = "fuzz_targets/mount_parsing.rs"
test = false
doc = false
bench = false
19 changes: 16 additions & 3 deletions fuzz/fuzz_targets/kernel_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,22 @@ use NVRC::nvrc::NVRC;
fuzz_target!(|data: &[u8]| {
// Only fuzz valid UTF-8 strings (kernel cmdline is always ASCII/UTF-8)
if let Ok(input) = std::str::from_utf8(data) {
let mut nvrc = NVRC::default();
// Ignore result - we're testing for panics, not correctness
let _ = nvrc.process_kernel_params(Some(input));
// NVRC is fail-fast: invalid numeric params must panic and reboot the VM.
// Swallow only those known validation panics; re-raise anything else so
// libFuzzer still catches genuine parser bugs.
if let Err(payload) = std::panic::catch_unwind(|| {
let mut nvrc = NVRC::default();
nvrc.process_kernel_params(Some(input));
}) {
let msg = payload
.downcast_ref::<&str>()
.copied()
.or_else(|| payload.downcast_ref::<String>().map(String::as_str))
.unwrap_or("");
if !msg.contains("nvrc.smi.") {
std::panic::resume_unwind(payload);
}
Comment thread
zvonkok marked this conversation as resolved.
}
}
});

19 changes: 19 additions & 0 deletions fuzz/fuzz_targets/mount_parsing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! Fuzz target for /proc/filesystems parsing.
//!
//! Tests that arbitrary /proc/filesystems content and fstype strings never
//! panic or produce memory-safety bugs in the availability check logic.

#![no_main]

use libfuzzer_sys::fuzz_target;
use NVRC::mount::fs_available;

fuzz_target!(|data: &[u8]| {
if let Ok(input) = std::str::from_utf8(data) {
// Split at the first NUL-like separator to get two independent string
// arguments; fall back to the whole input as filesystems with a fixed
// fstype so the fuzzer still exercises the line-scan path.
let (filesystems, fstype) = input.split_once('\x00').unwrap_or((input, "tmpfs"));
let _ = fs_available(filesystems, fstype);
}
});
9 changes: 7 additions & 2 deletions src/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ fn mount(source: &str, target: &str, fstype: &str, flags: MsFlags, data: Option<
}

/// Check if a filesystem type is available in the kernel.
fn fs_available(filesystems: &str, fstype: &str) -> bool {
filesystems.lines().any(|line| line.contains(fstype))
pub fn fs_available(filesystems: &str, fstype: &str) -> bool {
// /proc/filesystems lines: optional "nodev\t" prefix then the fs name.
// Match the last token exactly so "mp" does not accidentally match "tmpfs".
!fstype.is_empty()
&& filesystems
.lines()
.any(|line| line.split_whitespace().last() == Some(fstype))
}

/// Mount optional filesystem if the fstype is available AND the target exists.
Expand Down
Loading