void file descriptors
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing

This commit is contained in:
Jake Hillion 2022-04-08 17:23:39 +01:00
parent c511d12a5a
commit 04c2a85e3a
2 changed files with 32 additions and 17 deletions

View File

@ -11,7 +11,6 @@ use std::fs::File;
use std::io::Read; use std::io::Read;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use close_fds::CloseFdsBuilder;
use nix::unistd; use nix::unistd;
const BUFFER_SIZE: usize = 1024; const BUFFER_SIZE: usize = 1024;
@ -53,24 +52,17 @@ impl<'a> Spawner<'a> {
Trigger::Pipe(s) => { Trigger::Pipe(s) => {
let pipe = self.pipes.get_mut(s).unwrap().take_read(); let pipe = self.pipes.get_mut(s).unwrap().take_read();
let closure = || { let mut builder = VoidBuilder::new();
let mut closer = CloseFdsBuilder::new(); builder.keep_fd(&pipe);
let keep = [pipe.as_raw_fd()];
closer.keep_fds(&keep);
unsafe {
closer.closefrom(3);
}
match self.pipe_trigger(pipe, entrypoint, name) { let closure = || match self.pipe_trigger(pipe, entrypoint, name) {
Ok(()) => std::process::exit(exitcode::OK), Ok(()) => std::process::exit(exitcode::OK),
Err(e) => { Err(e) => {
error!("error in pipe_trigger: {}", e); error!("error in pipe_trigger: {}", e);
std::process::exit(1) std::process::exit(1)
}
} }
}; };
let mut builder = VoidBuilder::new();
builder.spawn(closure)?; builder.spawn(closure)?;
} }
} }

View File

@ -3,8 +3,9 @@ use log::{debug, error};
use crate::clone::{clone3, CloneArgs, CloneFlags}; use crate::clone::{clone3, CloneArgs, CloneFlags};
use crate::{Error, Result}; use crate::{Error, Result};
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::fs; use std::fs;
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::PathBuf; use std::path::PathBuf;
use nix::mount::{mount, umount2, MntFlags, MsFlags}; use nix::mount::{mount, umount2, MntFlags, MsFlags};
@ -12,17 +13,20 @@ use nix::sched::unshare;
use nix::sys::signal::Signal; use nix::sys::signal::Signal;
use nix::unistd::{pivot_root, Pid}; use nix::unistd::{pivot_root, Pid};
use close_fds::CloseFdsBuilder;
pub struct VoidHandle {} pub struct VoidHandle {}
pub struct VoidBuilder { pub struct VoidBuilder {
#[allow(dead_code)]
mounts: HashMap<PathBuf, PathBuf>, mounts: HashMap<PathBuf, PathBuf>,
fds: HashSet<RawFd>,
} }
impl VoidBuilder { impl VoidBuilder {
pub fn new() -> VoidBuilder { pub fn new() -> VoidBuilder {
VoidBuilder { VoidBuilder {
mounts: HashMap::new(), mounts: HashMap::new(),
fds: HashSet::new(),
} }
} }
@ -32,6 +36,11 @@ impl VoidBuilder {
self 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<VoidHandle> { pub fn spawn(&mut self, child_fn: impl FnOnce() -> i32) -> Result<VoidHandle> {
let mut args = CloneArgs::new( let mut args = CloneArgs::new(
CloneFlags::CLONE_NEWCGROUP CloneFlags::CLONE_NEWCGROUP
@ -50,6 +59,7 @@ impl VoidBuilder {
if child == Pid::from_raw(0) { if child == Pid::from_raw(0) {
let result = { let result = {
self.void_files()?;
self.void_mount_namespace()?; self.void_mount_namespace()?;
self.void_user_namespace()?; // last to maintain permissions self.void_user_namespace()?; // last to maintain permissions
@ -77,6 +87,19 @@ impl VoidBuilder {
} }
// per-namespace void creation // 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<()> { fn void_mount_namespace(&self) -> Result<()> {
// change the propagation type of the old root to private // change the propagation type of the old root to private
mount( mount(