diff --git a/Cargo.toml b/Cargo.toml index 2bd5e09..b386d5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ clap = { version = "4.4.7", features = ["derive"] } env_logger = "0.10.0" libseccomp = "0.3.0" log = "0.4.20" -nix = { version = "0.27.1", features = [ "process", "ptrace", "signal" ] } +nix = { version = "0.27.1", features = [ "process", "ptrace", "signal", "fs" ] } x2t-sandbox-rulegen = { path = "./x2t-sandbox-rulegen" } [build-dependencies] diff --git a/src/main.rs b/src/main.rs index 46d5a44..0d00321 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use nix::{ libc::{c_long, EPERM, ORIG_RAX}, + sys::stat::Mode, unistd::{getpid, getppid}, }; use std::io::Write; @@ -106,14 +107,19 @@ fn main() -> anyhow::Result<()> { .map(|s| CString::new(s.as_str()).unwrap()) .collect(); log::trace!("command: {command:?}"); - let executable = CString::new(args.command[0].clone()).unwrap(); - log::trace!("executable: {executable:?}"); + log::trace!("executable: {:?}", args.command[0]); let env: Vec = std::env::vars() .into_iter() .map(|(k, v)| format!("{k}={v}")) .map(|s| CString::new(s).unwrap()) .collect(); + let exe_fd = nix::fcntl::open( + format!("{}", args.command[0]).as_str(), + nix::fcntl::OFlag::O_RDONLY | nix::fcntl::OFlag::O_PATH, + Mode::empty(), + )?; + #[cfg(feature = "tracing-mode")] if tracing { // i'm child. trace me @@ -133,9 +139,14 @@ fn main() -> anyhow::Result<()> { log::trace!("create filter context..."); let mut filter = ScmpFilterContext::new_filter(default_action)?; - filter.add_rule( - ScmpAction::Log, - ScmpSyscall::from(nix::libc::SYS_execve as i32), + filter.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from(nix::libc::SYS_execveat as i32), + &[ScmpArgCompare::new( + 0, + libseccomp::ScmpCompareOp::Equal, + exe_fd as u64, + )], )?; x2t_sandbox_rulegen::generate! { @@ -153,9 +164,10 @@ fn main() -> anyhow::Result<()> { log::trace!("loaded"); log::debug!("executing {:?}", args.command); - if let Err(err) = nix::unistd::execve(&executable, command.as_slice(), env.as_slice()) { + if let Err(err) = nix::unistd::fexecve(exe_fd, command.as_slice(), env.as_slice()) { panic!("failed to execve for {err}"); } panic!("unreachable"); } +