Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

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);
    }
}