mirror of
https://github.com/marcoallegretti/WEFT_OS.git
synced 2026-03-27 01:13: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]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
wasmtime-runtime = ["dep:wasmtime", "dep:wasmtime-wasi", "dep:cap-std"]
|
wasmtime-runtime = ["dep:wasmtime", "dep:wasmtime-wasi", "dep:cap-std"]
|
||||||
|
seccomp = ["dep:seccompiler", "dep:libc"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
@ -19,3 +20,5 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
wasmtime = { version = "30", optional = true }
|
wasmtime = { version = "30", optional = true }
|
||||||
wasmtime-wasi = { version = "30", optional = true }
|
wasmtime-wasi = { version = "30", optional = true }
|
||||||
cap-std = { version = "3", 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;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "seccomp")]
|
||||||
|
apply_seccomp_filter().context("apply seccomp filter")?;
|
||||||
|
|
||||||
tracing::info!(session_id, %app_id, "weft-runtime starting");
|
tracing::info!(session_id, %app_id, "weft-runtime starting");
|
||||||
|
|
||||||
let pkg_dir = resolve_package(app_id)?;
|
let pkg_dir = resolve_package(app_id)?;
|
||||||
|
|
@ -168,6 +171,59 @@ fn run_module(
|
||||||
.map_err(|()| anyhow::anyhow!("wasm component run exited with error"))
|
.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> {
|
fn package_store_roots() -> Vec<PathBuf> {
|
||||||
if let Ok(explicit) = std::env::var("WEFT_APP_STORE") {
|
if let Ok(explicit) = std::env::var("WEFT_APP_STORE") {
|
||||||
return vec![PathBuf::from(explicit)];
|
return vec![PathBuf::from(explicit)];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue