From 550037e0b3a13ac2a2301fc03d84fe53d948e790 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 9 Oct 2026 16:24:58 +0200 Subject: [PATCH] mind-body: pin the creation modes, the non-root refusal and the dial decode branch Modes under umask 000/022/077 via a re-executed test child; a non-root user (setpriv uid 65534, skipped with a message when not root) cannot write the store but can read it; an undecodable or NaN dial reads Held(Undecodable) whatever the brake says, which kills the fail-open default-dial mutant. Co-Authored-By: Claude Opus 5.5 --- crates/mind-body/tests/control.rs | 121 ++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/crates/mind-body/tests/control.rs b/crates/mind-body/tests/control.rs index f6d4a1d..2293afc 100644 --- a/crates/mind-body/tests/control.rs +++ b/crates/mind-body/tests/control.rs @@ -293,3 +293,124 @@ fn the_control_path_is_derived_from_a_valid_instance_only() { assert!(control_path(root, &Slug(bad.into())).is_err(), "{bad:?}"); } } + +/// A dial document under the dial's type id whose payload is not a dial. +#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)] +#[cultcache(type = "eureka.control.burn_rate.v1", schema = "ControlBurnRate")] +struct WrongDial { + #[cultcache(key = 0)] + heat: String, +} + +fn write_wrong_dial(path: &Path, heat: &str) { + let mut cache = CultCache::new(); + cache.register_entry_type::().unwrap(); + cache.add_generic_backing_store(SingleFileMessagePackBackingStore::new(path)).unwrap(); + cache.pull_all_backing_stores().unwrap(); + cache.put(mind_body::control::DIAL_KEY, &WrongDial { heat: heat.into() }).unwrap(); +} + +#[test] +fn a_dial_that_does_not_decode_reads_held_whatever_the_brake_says() { + for brake_released in [true, false] { + for heat in ["not a number", "NaN", ""] { + let dir = tempfile::tempdir().unwrap(); + let path = store_path(dir.path()); + ControlWriter::open(&path).unwrap().set_brake(brake_released, at(0), "op").unwrap(); + write_wrong_dial(&path, heat); + assert_eq!( + effective(&path), + held(HeldReason::Undecodable), + "brake released={brake_released}, dial heat {heat:?}: a dial that cannot be read is never replaced by a default" + ); + } + } +} + +#[cfg(unix)] +mod modes { + use super::*; + use std::os::unix::fs::PermissionsExt; + use std::process::Command; + + const CHILD: &str = "MIND_BODY_MODE_CHILD"; + const ROOT: &str = "MIND_BODY_MODE_ROOT"; + + fn mode(path: &Path) -> u32 { + std::fs::metadata(path).unwrap().permissions().mode() & 0o777 + } + + /// The body of the two re-executed children; with no CHILD set it does + /// nothing, so a plain run of the suite passes it vacuously. + #[test] + fn mode_child() { + let Ok(role) = std::env::var(CHILD) else { return }; + let path = Path::new(&std::env::var(ROOT).unwrap()).join("eureka").join("control.cc"); + match role.as_str() { + "write" => { + let mut writer = ControlWriter::open(&path).unwrap(); + writer.set_brake(true, at(0), "op").unwrap(); + writer.set_dial(dial("1", 3600, "1")).unwrap(); + } + "intruder" => { + assert!(ControlWriter::open(&path).and_then(|mut writer| writer.set_brake(false, at(1), "intruder")).is_err()); + assert!(ControlWriter::open(Path::new(&std::env::var(ROOT).unwrap()).join("ghost").join("control.cc")) + .and_then(|mut writer| writer.set_brake(true, at(1), "intruder")) + .is_err()); + assert!(std::fs::OpenOptions::new().write(true).open(&path).is_err()); + assert!(std::fs::OpenOptions::new().write(true).open(path.with_file_name("control.cc.lock")).is_err()); + assert!(matches!(effective(&path), Effective::Released { .. }), "a non-root user can still read the store"); + } + other => panic!("unknown role {other}"), + } + } + + fn spawn_child(role: &str, root: &Path, exe: &Path, prefix: &[&str], umask: &str) -> std::process::ExitStatus { + let script = format!("umask {umask}; exec \"$@\" --exact modes::mode_child --nocapture"); + let mut command = Command::new(prefix.first().copied().unwrap_or("sh")); + if prefix.is_empty() { + command.args(["-c", &script, "sh"]).arg(exe); + } else { + command.args(&prefix[1..]).args(["sh", "-c", &script, "sh"]).arg(exe); + } + command.env(CHILD, role).env(ROOT, root).status().unwrap() + } + + fn written_under(umask: &str) -> (tempfile::TempDir, PathBuf) { + let dir = tempfile::tempdir().unwrap(); + std::fs::set_permissions(dir.path(), std::fs::Permissions::from_mode(0o755)).unwrap(); + let exe = std::env::current_exe().unwrap(); + assert!(spawn_child("write", dir.path(), &exe, &[], umask).success()); + let control = dir.path().join("eureka"); + (dir, control) + } + + #[test] + fn the_store_is_created_0755_and_0644_whatever_the_operators_umask() { + for umask in ["000", "022", "077"] { + let (_dir, control) = written_under(umask); + assert_eq!(mode(&control), 0o755, "directory under umask {umask}"); + assert_eq!(mode(&control.join("control.cc")), 0o644, "store under umask {umask}"); + assert_eq!(mode(&control.join("control.cc.lock")), 0o644, "lock under umask {umask}"); + } + } + + fn running_as_root() -> bool { + Command::new("id").arg("-u").output().map(|out| String::from_utf8_lossy(&out.stdout).trim() == "0").unwrap_or(false) + } + + #[test] + fn a_non_root_user_cannot_write_the_store_but_can_read_it() { + if !running_as_root() || Command::new("setpriv").arg("--version").output().is_err() { + eprintln!("SKIPPED: needs root and setpriv (the verify container has both) to become uid 65534"); + return; + } + let (dir, _control) = written_under("000"); + // A copy of the test binary the unprivileged user can execute. + let exe = dir.path().join("test-bin"); + std::fs::copy(std::env::current_exe().unwrap(), &exe).unwrap(); + std::fs::set_permissions(&exe, std::fs::Permissions::from_mode(0o755)).unwrap(); + let status = spawn_child("intruder", dir.path(), &exe, &["setpriv", "--reuid=65534", "--regid=65534", "--clear-groups"], "022"); + assert!(status.success(), "the intruder child asserted a refusal that did not happen"); + } +}