lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit 331fbb99cfdfd13cd34e6d843e9f92ce5380e697
parent 3c6eb71aa13ac9495c2b584342f113fd33add131
Author: triesap <tyson@radroots.org>
Date:   Thu,  6 Aug 2026 07:32:52 +0000

mobile: define windows logging acl and reparse behavior

- fail closed before any file mutation when Windows ACL enforcement is unavailable
- prohibit file logging until reparse-point checks are active
- retain stdout logging as the supported secure Windows capability
- cover the capability boundary with a Windows-targeted regression

Diffstat:
Mcrates/mobile_ffi/src/logging.rs | 23+++++++++++++++++++++++
Mcrates/mobile_ffi/src/logging/writer.rs | 4++--
2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/crates/mobile_ffi/src/logging.rs b/crates/mobile_ffi/src/logging.rs @@ -116,6 +116,13 @@ type FileWriter = tracing_appender::non_blocking::NonBlocking; fn build_file_writer( options: &LoggingOptions, ) -> Result<(Option<FileWriter>, Option<WorkerGuard>), String> { + #[cfg(windows)] + if options.dir.is_some() { + return Err( + "secure file logging is unavailable until Windows ACL and reparse-point enforcement is active" + .to_owned(), + ); + } let Some(dir) = options.dir.as_ref() else { return Ok((None, None)); }; @@ -247,6 +254,22 @@ mod tests { log_debug("debug".to_owned()).expect("debug"); } + #[cfg(windows)] + #[test] + fn windows_file_logging_fails_before_filesystem_mutation() { + let directory = tempfile::tempdir().expect("temporary directory"); + let requested = directory.path().join("must-not-exist"); + let options = LoggingOptions { + dir: Some(requested.clone()), + stdout: false, + ..LoggingOptions::default() + }; + let error = build_file_writer(&options).expect_err("ACL capability must fail closed"); + assert!(error.contains("ACL")); + assert!(error.contains("reparse-point")); + assert!(!requested.exists()); + } + #[test] fn initialization_is_idempotent_but_rejects_reconfiguration() { let directory = tempfile::tempdir().expect("temporary directory"); diff --git a/crates/mobile_ffi/src/logging/writer.rs b/crates/mobile_ffi/src/logging/writer.rs @@ -159,7 +159,7 @@ impl Write for SizeRotatingWriter { } } -#[cfg(any(test, not(unix)))] +#[cfg(test)] fn reject_unsafe_target(path: &Path) -> io::Result<()> { match fs::symlink_metadata(path) { Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_file() => Err( @@ -230,7 +230,7 @@ fn open_append(_path: &Path) -> io::Result<File> { )) } -#[cfg(any(test, not(unix)))] +#[cfg(test)] fn rotated_path(path: &Path, index: usize) -> PathBuf { let mut value = path.as_os_str().to_owned(); value.push(format!(".{index}"));