From b79cb0d6650ea2abf39c3f46035afa323e586d3a Mon Sep 17 00:00:00 2001 From: Zvonko Kaiser Date: Mon, 13 Jul 2026 16:15:10 +0000 Subject: [PATCH 1/2] fuzz: fix kernel_params crashes and add missing mount_parsing target kernel_params fuzzer was reporting intentional fail-fast panics (invalid u32 for lgc/lmc/pl) as crashes; wrap in catch_unwind so libFuzzer focuses on unexpected panics in the parsing logic. mount_parsing target was referenced in the CI matrix but never existed; expose fs_available as pub and add the fuzz target + Cargo.toml entry. Signed-off-by: Zvonko Kaiser Assisted-By: Claude Sonnet 4.6 --- fuzz/Cargo.toml | 8 ++++++++ fuzz/fuzz_targets/kernel_params.rs | 10 +++++++--- fuzz/fuzz_targets/mount_parsing.rs | 19 +++++++++++++++++++ src/mount.rs | 2 +- 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 fuzz/fuzz_targets/mount_parsing.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index f4b50f18..55e4f316 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -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 diff --git a/fuzz/fuzz_targets/kernel_params.rs b/fuzz/fuzz_targets/kernel_params.rs index 0443dcf2..72757c00 100644 --- a/fuzz/fuzz_targets/kernel_params.rs +++ b/fuzz/fuzz_targets/kernel_params.rs @@ -12,9 +12,13 @@ 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. + // catch_unwind keeps libFuzzer focused on unexpected crashes in the + // parsing and splitting logic, not the intended validation panics. + let _ = std::panic::catch_unwind(|| { + let mut nvrc = NVRC::default(); + nvrc.process_kernel_params(Some(input)); + }); } }); diff --git a/fuzz/fuzz_targets/mount_parsing.rs b/fuzz/fuzz_targets/mount_parsing.rs new file mode 100644 index 00000000..ba0ea87d --- /dev/null +++ b/fuzz/fuzz_targets/mount_parsing.rs @@ -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); + } +}); diff --git a/src/mount.rs b/src/mount.rs index e00d08f3..91c6afd2 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -15,7 +15,7 @@ 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 { +pub fn fs_available(filesystems: &str, fstype: &str) -> bool { filesystems.lines().any(|line| line.contains(fstype)) } From 52b4ee5443c7fbb114f3a8c37a0537cdd088ae33 Mon Sep 17 00:00:00 2001 From: Zvonko Kaiser Date: Mon, 13 Jul 2026 19:02:05 +0000 Subject: [PATCH 2/2] fuzz: address review comments fs_available: match exact last token per line instead of substring so "mp" no longer false-positives against "tmpfs"; empty fstype returns false. kernel_params harness: re-raise panics whose message does not contain "nvrc.smi." so genuine parser bugs still surface as libFuzzer crashes. Signed-off-by: Zvonko Kaiser Assisted-By: Claude Sonnet 4.6 --- fuzz/fuzz_targets/kernel_params.rs | 17 +++++++++++++---- src/mount.rs | 7 ++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/fuzz/fuzz_targets/kernel_params.rs b/fuzz/fuzz_targets/kernel_params.rs index 72757c00..6e2b86f5 100644 --- a/fuzz/fuzz_targets/kernel_params.rs +++ b/fuzz/fuzz_targets/kernel_params.rs @@ -13,12 +13,21 @@ 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) { // NVRC is fail-fast: invalid numeric params must panic and reboot the VM. - // catch_unwind keeps libFuzzer focused on unexpected crashes in the - // parsing and splitting logic, not the intended validation panics. - let _ = std::panic::catch_unwind(|| { + // 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::().map(String::as_str)) + .unwrap_or(""); + if !msg.contains("nvrc.smi.") { + std::panic::resume_unwind(payload); + } + } } }); diff --git a/src/mount.rs b/src/mount.rs index 91c6afd2..521b9676 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -16,7 +16,12 @@ fn mount(source: &str, target: &str, fstype: &str, flags: MsFlags, data: Option< /// Check if a filesystem type is available in the kernel. pub fn fs_available(filesystems: &str, fstype: &str) -> bool { - filesystems.lines().any(|line| line.contains(fstype)) + // /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.