117 lines
4.3 KiB
Rust
117 lines
4.3 KiB
Rust
#![cfg(target_os = "linux")]
|
|
mod support;
|
|
use kf_sandbox::{
|
|
artifacts::ArtifactRoot,
|
|
launcher::seccomp::FilteredTarget,
|
|
outcome::ExecutionStage,
|
|
spec::{ExecutionProfile, SpecPolicy},
|
|
};
|
|
use std::{fs, os::unix::fs::PermissionsExt, path::Path, process::Command};
|
|
|
|
fn check(profile: ExecutionProfile, name: &str) {
|
|
let root = support::Root::new();
|
|
let before = support::children();
|
|
let path = format!("/kf/seccomp-publications-{}", std::process::id());
|
|
fs::create_dir(&path).unwrap();
|
|
fs::set_permissions(&path, fs::Permissions::from_mode(0o700)).unwrap();
|
|
fs::write(format!("{path}/program-001"), b"fixed-non-task-payload").unwrap();
|
|
fs::write(format!("{path}/input-001"), b"private-stdin").unwrap();
|
|
let artifacts = ArtifactRoot::from_directory(
|
|
rustix::fs::open(
|
|
&path,
|
|
rustix::fs::OFlags::PATH | rustix::fs::OFlags::DIRECTORY | rustix::fs::OFlags::CLOEXEC,
|
|
rustix::fs::Mode::empty(),
|
|
)
|
|
.unwrap(),
|
|
)
|
|
.unwrap();
|
|
let mut spec = support::spec("seccomp-fixture", 64 << 20, 8).spec().clone();
|
|
spec.run_id = format!("seccomp-{name}");
|
|
spec.profile = profile;
|
|
if profile != ExecutionProfile::Native {
|
|
spec.argv = vec![
|
|
if profile == ExecutionProfile::CompileC {
|
|
"/usr/bin/gcc"
|
|
} else {
|
|
"/usr/bin/g++"
|
|
}
|
|
.into(),
|
|
"/work/main".into(),
|
|
];
|
|
}
|
|
let result = FilteredTarget::prepare(
|
|
&root.validated(),
|
|
&spec.validate(&SpecPolicy::default()).unwrap(),
|
|
&support::binary(),
|
|
&artifacts,
|
|
);
|
|
if std::env::var("KF_SANDBOX_DENY_SECCOMP").as_deref() == Ok("1") {
|
|
let Err(e) = result else {
|
|
panic!("kernel policy failure ignored")
|
|
};
|
|
assert_eq!(e.failure.stage, ExecutionStage::Seccomp);
|
|
assert_eq!(e.failure.errno, Some(1));
|
|
assert!(e.cleanup_failure.is_none());
|
|
println!("KF_SECCOMP_FAILURE_PROOF real_eperm=1 no_ack=1 target_reaped=1 lease_released=1");
|
|
} else {
|
|
let target = result.unwrap();
|
|
let status =
|
|
fs::read_to_string(format!("/proc/{}/status", target.root().init_pid())).unwrap();
|
|
assert!(status.contains("Seccomp:\t2\n"));
|
|
assert!(status.contains("Seccomp_filters:\t1\n"));
|
|
assert!(status.contains("NoNewPrivs:\t1\n"));
|
|
assert_eq!(target.identity(), (100000, 100000));
|
|
assert!(target.root().snapshot_outputs().unwrap().is_empty());
|
|
let e = target.refuse_remaining_isolation();
|
|
assert_eq!(e.failure.stage, ExecutionStage::Exec);
|
|
assert!(e.cleanup_failure.is_none());
|
|
let output = Command::new("/kf/bin/seccomp-probe")
|
|
.arg(name)
|
|
.env_clear()
|
|
.env("KF_SANDBOX_INDEPENDENT_VM", "1")
|
|
.output()
|
|
.unwrap();
|
|
assert!(
|
|
output.status.success(),
|
|
"{:?} {:?}",
|
|
String::from_utf8_lossy(&output.stdout),
|
|
String::from_utf8_lossy(&output.stderr)
|
|
);
|
|
print!("{}", String::from_utf8_lossy(&output.stdout));
|
|
println!(
|
|
"KF_SECCOMP_INIT_PROOF profile={name} frozen=1 filter_count=1 identity=1 run_refused=1"
|
|
);
|
|
}
|
|
assert_eq!(support::children(), before);
|
|
assert_eq!(
|
|
fs::read_dir("/var/lib/kf-judge/identities")
|
|
.unwrap()
|
|
.count(),
|
|
0
|
|
);
|
|
assert!(!Path::new(&format!("/var/lib/kf-judge/tasks/kf-seccomp-{name}")).exists());
|
|
assert!(!root.path.join(format!("kf-seccomp-{name}")).exists());
|
|
fs::remove_dir_all(path).unwrap();
|
|
}
|
|
#[test]
|
|
#[ignore = "requires independent capped VM"]
|
|
fn native_policy_installs_and_inherits() {
|
|
check(ExecutionProfile::Native, "native");
|
|
}
|
|
#[test]
|
|
#[ignore = "requires independent capped VM"]
|
|
fn compile_c_policy_installs_and_inherits() {
|
|
check(ExecutionProfile::CompileC, "compile-c");
|
|
}
|
|
#[test]
|
|
#[ignore = "requires independent capped VM"]
|
|
fn compile_cpp_policy_installs_and_inherits() {
|
|
check(ExecutionProfile::CompileCpp, "compile-cpp");
|
|
}
|
|
#[test]
|
|
#[ignore = "requires independent capped VM with kernel seccomp failure injector"]
|
|
fn kernel_seccomp_failure_refuses_and_cleans() {
|
|
assert_eq!(std::env::var("KF_SANDBOX_DENY_SECCOMP").as_deref(), Ok("1"));
|
|
check(ExecutionProfile::Native, "native");
|
|
}
|