jobs/runner/src/seccomp.rs
//! **The scan worker's GENERATED seccomp profile** (lane HEIMDALL-ALLIN prof, feature
//! `heimdall`).
//!
//! `seccomp/holger-scan-worker/` holds the profile `heimdall profile gen` (Heimdall 0.3,
//! heimdall-probe) wrote from what the static `holger-scan-worker` really called in learning
//! mode, in the job shape Heimdall's runner gives it (argv `[/holger-scan-worker]`, `/in`
//! read-only, `/out` write-only, the job's rlimits), over its real jobs: verify-bundle
//! (native and the split wasm guest) and scans of real packages. Nothing in it was widened
//! by hand; the README there lists the corpus and how to measure it again.
//!
//! [`scan_worker_profile`] writes the reviewed OCI seccomp JSON (compiled in) to the
//! server's Heimdall work directory and names it, pinned by its SHA-256, so Heimdall's runner
//! installs it on top of its fixed profile; a call outside it ends the job (Heimdall
//! `heimdall-seccomp-1`, Holger `holger-sandbox-3`, killed).
use std::path::Path;
use heimdall_core::{ProfileSource, SeccompProfileRef};
/// The reviewed OCI seccomp JSON of the static (musl) worker on x86_64.
#[cfg(target_arch = "x86_64")]
pub const SCAN_WORKER_OCI_JSON: &[u8] =
include_bytes!("../seccomp/holger-scan-worker/x86_64-musl.oci.json");
/// Its pin: `sha256:` of [`SCAN_WORKER_OCI_JSON`]. A changed profile changes this line too,
/// so a profile change is always a reviewed diff of two files.
#[cfg(target_arch = "x86_64")]
pub const SCAN_WORKER_SHA256: &str =
"sha256:6d802b5e35790a95557df21da031b536a572d916a3269167d68abf9ae8ba752a";
/// The file name the profile is written under in the Heimdall work directory.
pub const FILE_NAME: &str = "holger-scan-worker.x86_64-musl.oci.json";
/// Write the worker's profile into `dir` (created; the file replaced, never through a
/// symlink) and name it, pinned. `None` on an arch with no measured profile: the jobs then
/// run under Heimdall's fixed profile only.
pub fn scan_worker_profile(dir: &Path) -> Result<Option<SeccompProfileRef>, String> {
#[cfg(target_arch = "x86_64")]
{
let err = |e: std::io::Error| {
format!(
"heimdall: the worker's seccomp profile in {}: {e}",
dir.display()
)
};
std::fs::create_dir_all(dir).map_err(err)?;
let path = dir.join(FILE_NAME);
let tmp = dir.join(format!(".{FILE_NAME}.tmp"));
let _ = std::fs::remove_file(&tmp);
std::fs::write(&tmp, SCAN_WORKER_OCI_JSON).map_err(err)?;
std::fs::rename(&tmp, &path).map_err(err)?;
Ok(Some(SeccompProfileRef {
source: ProfileSource::OciFile(path),
sha256: SCAN_WORKER_SHA256.into(),
fallback_to_default: false,
}))
}
#[cfg(not(target_arch = "x86_64"))]
{
let _ = dir;
Ok(None)
}
}
#[cfg(all(test, target_arch = "x86_64"))]
mod tests {
use super::*;
#[test]
fn the_compiled_in_profile_is_the_pinned_one() {
use sha2::Digest as _;
let got = format!(
"sha256:{}",
hex::encode(sha2::Sha256::digest(SCAN_WORKER_OCI_JSON))
);
assert_eq!(got, SCAN_WORKER_SHA256);
}
#[test]
fn the_profile_kills_every_call_it_does_not_name_and_has_no_exec_or_network() {
let v: serde_json::Value = serde_json::from_slice(SCAN_WORKER_OCI_JSON).unwrap();
assert_eq!(v["defaultAction"], "SCMP_ACT_KILL_PROCESS");
let names: Vec<&str> = v["syscalls"]
.as_array()
.unwrap()
.iter()
.flat_map(|s| {
s["names"]
.as_array()
.unwrap()
.iter()
.map(|n| n.as_str().unwrap())
})
.collect();
for never in [
"execve", "execveat", "socket", "connect", "bind", "ptrace", "mount", "unshare",
"setns",
] {
assert!(!names.contains(&never), "{never} in the worker profile");
}
}
#[test]
fn the_profile_is_written_where_heimdall_reads_it_and_named_by_its_pin() {
let d = tempfile::tempdir().unwrap();
let r = scan_worker_profile(&d.path().join("s")).unwrap().unwrap();
let ProfileSource::OciFile(p) = &r.source else {
panic!("{r:?}")
};
assert!(p.is_absolute() || d.path().is_relative());
assert_eq!(std::fs::read(p).unwrap(), SCAN_WORKER_OCI_JSON);
assert_eq!(r.sha256, SCAN_WORKER_SHA256);
assert!(!r.fallback_to_default);
}
}