use execveat instead of execve to limit execve

This commit is contained in:
guochao 2023-11-02 09:51:06 +08:00
parent d925fda57b
commit b38406c785
2 changed files with 19 additions and 7 deletions

View File

@ -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]

View File

@ -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<CString> = 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");
}