mirror of
https://github.com/marcoallegretti/WEFT_OS.git
synced 2026-03-26 17:03:09 +00:00
feat(runtime): seccomp blocklist filter via optional seccomp feature
Add seccomp feature flag (seccompiler + libc, Linux-only, optional). When compiled with --features seccomp, weft-runtime installs a SECCOMP_MODE_FILTER immediately after argument parsing, before any package resolution or WASM execution. Filter strategy: default-allow with explicit KillProcess rules for high-risk syscalls a WASM runtime process has no legitimate need for: ptrace, process_vm_readv/writev, kexec_load, personality, syslog, reboot, mount/umount2, setuid/setgid/setreuid/setregid/setresuid/ setresgid, chroot, pivot_root, init_module/finit_module/delete_module, bpf, perf_event_open, acct. The feature is off by default so the standard build and tests are unaffected. Enable in production service builds with --features seccomp.
This commit is contained in:
parent
ec4cc272af
commit
98a21da734
2 changed files with 59 additions and 0 deletions
|
|
@ -11,6 +11,7 @@ path = "src/main.rs"
|
|||
[features]
|
||||
default = []
|
||||
wasmtime-runtime = ["dep:wasmtime", "dep:wasmtime-wasi", "dep:cap-std"]
|
||||
seccomp = ["dep:seccompiler", "dep:libc"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
|
|
@ -19,3 +20,5 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|||
wasmtime = { version = "30", optional = true }
|
||||
wasmtime-wasi = { version = "30", optional = true }
|
||||
cap-std = { version = "3", optional = true }
|
||||
seccompiler = { version = "0.4", optional = true }
|
||||
libc = { version = "0.2", optional = true }
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ fn main() -> anyhow::Result<()> {
|
|||
i += 1;
|
||||
}
|
||||
|
||||
#[cfg(feature = "seccomp")]
|
||||
apply_seccomp_filter().context("apply seccomp filter")?;
|
||||
|
||||
tracing::info!(session_id, %app_id, "weft-runtime starting");
|
||||
|
||||
let pkg_dir = resolve_package(app_id)?;
|
||||
|
|
@ -168,6 +171,59 @@ fn run_module(
|
|||
.map_err(|()| anyhow::anyhow!("wasm component run exited with error"))
|
||||
}
|
||||
|
||||
#[cfg(feature = "seccomp")]
|
||||
fn apply_seccomp_filter() -> anyhow::Result<()> {
|
||||
use seccompiler::{BpfProgram, SeccompAction, SeccompFilter, SeccompRule};
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let arch = seccompiler::TargetArch::x86_64;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let arch = seccompiler::TargetArch::aarch64;
|
||||
|
||||
let blocked: &[i64] = &[
|
||||
libc::SYS_ptrace,
|
||||
libc::SYS_process_vm_readv,
|
||||
libc::SYS_process_vm_writev,
|
||||
libc::SYS_kexec_load,
|
||||
libc::SYS_personality,
|
||||
libc::SYS_syslog,
|
||||
libc::SYS_reboot,
|
||||
libc::SYS_mount,
|
||||
libc::SYS_umount2,
|
||||
libc::SYS_setuid,
|
||||
libc::SYS_setgid,
|
||||
libc::SYS_setreuid,
|
||||
libc::SYS_setregid,
|
||||
libc::SYS_setresuid,
|
||||
libc::SYS_setresgid,
|
||||
libc::SYS_chroot,
|
||||
libc::SYS_pivot_root,
|
||||
libc::SYS_init_module,
|
||||
libc::SYS_finit_module,
|
||||
libc::SYS_delete_module,
|
||||
libc::SYS_bpf,
|
||||
libc::SYS_perf_event_open,
|
||||
libc::SYS_acct,
|
||||
];
|
||||
|
||||
let mut rules: BTreeMap<i64, Vec<SeccompRule>> = BTreeMap::new();
|
||||
for &syscall in blocked {
|
||||
rules.insert(syscall, vec![SeccompRule::new(vec![])?]);
|
||||
}
|
||||
|
||||
let filter = SeccompFilter::new(
|
||||
rules,
|
||||
SeccompAction::Allow,
|
||||
SeccompAction::KillProcess,
|
||||
arch,
|
||||
)?;
|
||||
let bpf: BpfProgram = filter.try_into()?;
|
||||
seccompiler::apply_filter(&bpf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn package_store_roots() -> Vec<PathBuf> {
|
||||
if let Ok(explicit) = std::env::var("WEFT_APP_STORE") {
|
||||
return vec![PathBuf::from(explicit)];
|
||||
|
|
|
|||
Loading…
Reference in a new issue