bind mounts
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 19:26:13 +01:00
parent 04c2a85e3a
commit bb28c74833
2 changed files with 42 additions and 8 deletions

View File

@ -10,6 +10,7 @@ use std::ffi::CString;
use std::fs::File; 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 std::path::PathBuf;
use nix::unistd; use nix::unistd;
@ -29,10 +30,15 @@ impl<'a> Spawner<'a> {
match &entrypoint.trigger { match &entrypoint.trigger {
Trigger::Startup => { Trigger::Startup => {
let binary = PathBuf::from(self.binary).canonicalize()?;
let mut builder = VoidBuilder::new();
builder.mount(binary, "/entrypoint");
let closure = || { let closure = || {
let args = self.prepare_args(name, &entrypoint.args, None); let args = self.prepare_args(name, &entrypoint.args, None);
if let Err(e) = unistd::execv(&CString::new(self.binary).unwrap(), &args) if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
.map_err(|e| Error::Nix { .map_err(|e| Error::Nix {
msg: "execv", msg: "execv",
src: e, src: e,
@ -45,14 +51,15 @@ impl<'a> Spawner<'a> {
} }
}; };
let mut builder = VoidBuilder::new();
builder.spawn(closure)?; builder.spawn(closure)?;
} }
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 binary = PathBuf::from(self.binary).canonicalize()?;
let mut builder = VoidBuilder::new(); let mut builder = VoidBuilder::new();
builder.mount(binary, "/entrypoint");
builder.keep_fd(&pipe); builder.keep_fd(&pipe);
let closure = || match self.pipe_trigger(pipe, entrypoint, name) { let closure = || match self.pipe_trigger(pipe, entrypoint, name) {
@ -87,7 +94,7 @@ impl<'a> Spawner<'a> {
let pipe_trigger = std::str::from_utf8(&buf[0..read_bytes]).unwrap(); let pipe_trigger = std::str::from_utf8(&buf[0..read_bytes]).unwrap();
let args = self.prepare_args_ref(name, &spec.args, Some(pipe_trigger)); let args = self.prepare_args_ref(name, &spec.args, Some(pipe_trigger));
if let Err(e) = unistd::execv(&CString::new(self.binary).unwrap(), &args) if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
.map_err(|e| Error::Nix { .map_err(|e| Error::Nix {
msg: "execv", msg: "execv",
src: e, src: e,

View File

@ -6,7 +6,7 @@ use crate::{Error, Result};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs; use std::fs;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::path::PathBuf; use std::path::{Path, PathBuf};
use nix::mount::{mount, umount2, MntFlags, MsFlags}; use nix::mount::{mount, umount2, MntFlags, MsFlags};
use nix::sched::unshare; use nix::sched::unshare;
@ -31,8 +31,8 @@ impl VoidBuilder {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn mount(&mut self, src: PathBuf, dst: PathBuf) -> &mut Self { pub fn mount<T1: AsRef<Path>, T2: AsRef<Path>>(&mut self, src: T1, dst: T2) -> &mut Self {
self.mounts.insert(src, dst); self.mounts.insert(src.as_ref().into(), dst.as_ref().into());
self self
} }
@ -144,10 +144,37 @@ impl VoidBuilder {
// chdir after // chdir after
std::env::set_current_dir("/")?; std::env::set_current_dir("/")?;
// TODO: mount requested mounts // mount paths before unmounting old_root
for (src, dst) in &self.mounts {
let src = PathBuf::from("/old_root/").join(src.strip_prefix("/").unwrap_or(src));
let dst = PathBuf::from("/").join(dst);
debug!("mounting `{:?}` as `{:?}`", src, dst);
// create the target
let src_data = fs::metadata(&src)?;
if src_data.is_dir() {
fs::create_dir_all(&dst)?;
} else {
fs::write(&dst, b"")?;
}
// bind mount
mount(
Some(&src),
&dst,
Option::<&str>::None,
MsFlags::MS_BIND,
Option::<&str>::None,
)
.map_err(|e| Error::Nix {
msg: "mount",
src: e,
})?;
}
// unmount the old root // unmount the old root
umount2("old_root/", MntFlags::MNT_DETACH).map_err(|e| Error::Nix { umount2("/old_root/", MntFlags::MNT_DETACH).map_err(|e| Error::Nix {
msg: "umount2", msg: "umount2",
src: e, src: e,
})?; })?;