From 04c2a85e3a8d788b8e8112bdb1cf132d5329b12d Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Fri, 8 Apr 2022 17:23:39 +0100 Subject: [PATCH] void file descriptors --- src/spawner.rs | 22 +++++++--------------- src/void.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/spawner.rs b/src/spawner.rs index 06c0466..ad93a14 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -11,7 +11,6 @@ use std::fs::File; use std::io::Read; use std::os::unix::io::AsRawFd; -use close_fds::CloseFdsBuilder; use nix::unistd; const BUFFER_SIZE: usize = 1024; @@ -53,24 +52,17 @@ impl<'a> Spawner<'a> { Trigger::Pipe(s) => { let pipe = self.pipes.get_mut(s).unwrap().take_read(); - let closure = || { - let mut closer = CloseFdsBuilder::new(); - let keep = [pipe.as_raw_fd()]; - closer.keep_fds(&keep); - unsafe { - closer.closefrom(3); - } + let mut builder = VoidBuilder::new(); + builder.keep_fd(&pipe); - match self.pipe_trigger(pipe, entrypoint, name) { - Ok(()) => std::process::exit(exitcode::OK), - Err(e) => { - error!("error in pipe_trigger: {}", e); - std::process::exit(1) - } + let closure = || match self.pipe_trigger(pipe, entrypoint, name) { + Ok(()) => std::process::exit(exitcode::OK), + Err(e) => { + error!("error in pipe_trigger: {}", e); + std::process::exit(1) } }; - let mut builder = VoidBuilder::new(); builder.spawn(closure)?; } } diff --git a/src/void.rs b/src/void.rs index 1f2712b..f414b59 100644 --- a/src/void.rs +++ b/src/void.rs @@ -3,8 +3,9 @@ use log::{debug, error}; use crate::clone::{clone3, CloneArgs, CloneFlags}; use crate::{Error, Result}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fs; +use std::os::unix::io::{AsRawFd, RawFd}; use std::path::PathBuf; use nix::mount::{mount, umount2, MntFlags, MsFlags}; @@ -12,17 +13,20 @@ use nix::sched::unshare; use nix::sys::signal::Signal; use nix::unistd::{pivot_root, Pid}; +use close_fds::CloseFdsBuilder; + pub struct VoidHandle {} pub struct VoidBuilder { - #[allow(dead_code)] mounts: HashMap, + fds: HashSet, } impl VoidBuilder { pub fn new() -> VoidBuilder { VoidBuilder { mounts: HashMap::new(), + fds: HashSet::new(), } } @@ -32,6 +36,11 @@ impl VoidBuilder { self } + pub fn keep_fd(&mut self, fd: &impl AsRawFd) -> &mut Self { + self.fds.insert(fd.as_raw_fd()); + self + } + pub fn spawn(&mut self, child_fn: impl FnOnce() -> i32) -> Result { let mut args = CloneArgs::new( CloneFlags::CLONE_NEWCGROUP @@ -50,6 +59,7 @@ impl VoidBuilder { if child == Pid::from_raw(0) { let result = { + self.void_files()?; self.void_mount_namespace()?; self.void_user_namespace()?; // last to maintain permissions @@ -77,6 +87,19 @@ impl VoidBuilder { } // per-namespace void creation + fn void_files(&self) -> Result<()> { + let mut closer = CloseFdsBuilder::new(); + + let keep: Box<[RawFd]> = self.fds.iter().copied().collect(); + closer.keep_fds(&keep); + + unsafe { + closer.closefrom(3); + } + + Ok(()) + } + fn void_mount_namespace(&self) -> Result<()> { // change the propagation type of the old root to private mount(