added mount namespace separation
This commit is contained in:
parent
f2c9dddb67
commit
c511d12a5a
@ -8,8 +8,9 @@ The basic example instructs the shim to spawn two processes, each of which write
|
|||||||
|
|
||||||
To run this example:
|
To run this example:
|
||||||
|
|
||||||
|
cargo build
|
||||||
cargo build --example basic
|
cargo build --example basic
|
||||||
cargo run -- -s examples/basic/spec.json target/debug/examples/basic
|
sudo target/debug/clone-shim -s examples/basic/spec.json target/debug/examples/basic
|
||||||
|
|
||||||
### examples/pipes
|
### examples/pipes
|
||||||
|
|
||||||
@ -17,5 +18,6 @@ The pipes example shows some of the power of the shim by using pipes. The proces
|
|||||||
|
|
||||||
To run this example:
|
To run this example:
|
||||||
|
|
||||||
|
cargo build
|
||||||
cargo build --example pipes
|
cargo build --example pipes
|
||||||
cargo run -- -s examples/pipes/spec.json target/debug/examples/pipes
|
sudo target/debug/clone-shim -s examples/pipes/spec.json target/debug/examples/pipes
|
||||||
|
74
src/void.rs
74
src/void.rs
@ -1,3 +1,5 @@
|
|||||||
|
use log::{debug, error};
|
||||||
|
|
||||||
use crate::clone::{clone3, CloneArgs, CloneFlags};
|
use crate::clone::{clone3, CloneArgs, CloneFlags};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
|
||||||
@ -5,7 +7,8 @@ use std::collections::HashMap;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use nix::mount::{mount, umount, MsFlags};
|
use nix::mount::{mount, umount2, MntFlags, MsFlags};
|
||||||
|
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};
|
||||||
|
|
||||||
@ -36,7 +39,6 @@ impl VoidBuilder {
|
|||||||
| CloneFlags::CLONE_NEWNET
|
| CloneFlags::CLONE_NEWNET
|
||||||
| CloneFlags::CLONE_NEWNS
|
| CloneFlags::CLONE_NEWNS
|
||||||
| CloneFlags::CLONE_NEWPID
|
| CloneFlags::CLONE_NEWPID
|
||||||
| CloneFlags::CLONE_NEWUSER
|
|
||||||
| CloneFlags::CLONE_NEWUTS,
|
| CloneFlags::CLONE_NEWUTS,
|
||||||
);
|
);
|
||||||
args.exit_signal = Some(Signal::SIGCHLD);
|
args.exit_signal = Some(Signal::SIGCHLD);
|
||||||
@ -47,10 +49,22 @@ impl VoidBuilder {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if child == Pid::from_raw(0) {
|
if child == Pid::from_raw(0) {
|
||||||
self.newns_post().unwrap();
|
let result = {
|
||||||
|
self.void_mount_namespace()?;
|
||||||
|
self.void_user_namespace()?; // last to maintain permissions
|
||||||
|
|
||||||
|
Ok::<(), Error>(())
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = result {
|
||||||
|
error!("error preparing void: {}", e);
|
||||||
|
std::process::exit(-1)
|
||||||
|
} else {
|
||||||
std::process::exit(child_fn())
|
std::process::exit(child_fn())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("cloned child: {}", child);
|
||||||
|
|
||||||
// Leak the child function's resources in the parent process.
|
// Leak the child function's resources in the parent process.
|
||||||
// This avoids closing files that have been "moved" into the child.
|
// This avoids closing files that have been "moved" into the child.
|
||||||
@ -63,12 +77,26 @@ impl VoidBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// per-namespace void creation
|
// per-namespace void creation
|
||||||
fn newns_post(&self) -> Result<()> {
|
fn void_mount_namespace(&self) -> Result<()> {
|
||||||
// consume the TempDir so it doesn't get deleted
|
// change the propagation type of the old root to private
|
||||||
let new_root = tempfile::tempdir()?.into_path();
|
|
||||||
|
|
||||||
mount(
|
mount(
|
||||||
Option::<&str>::None,
|
Option::<&str>::None,
|
||||||
|
"/",
|
||||||
|
Option::<&str>::None,
|
||||||
|
MsFlags::MS_PRIVATE,
|
||||||
|
Option::<&str>::None,
|
||||||
|
)
|
||||||
|
.map_err(|e| Error::Nix {
|
||||||
|
msg: "mount",
|
||||||
|
src: e,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// create and consume a tmpdir to mount a tmpfs into
|
||||||
|
let new_root = tempfile::tempdir()?.into_path();
|
||||||
|
|
||||||
|
// mount a tmpfs as the new root
|
||||||
|
mount(
|
||||||
|
Some("tmpfs"),
|
||||||
&new_root,
|
&new_root,
|
||||||
Some("tmpfs"),
|
Some("tmpfs"),
|
||||||
MsFlags::empty(),
|
MsFlags::empty(),
|
||||||
@ -79,19 +107,37 @@ impl VoidBuilder {
|
|||||||
src: e,
|
src: e,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// TODO: Mount mounts
|
// prepare a subdirectory to pivot the old root into
|
||||||
|
let put_old = new_root.join("old_root/");
|
||||||
|
debug!("new_root: {:?}; put_old: {:?}", &new_root, &put_old);
|
||||||
|
fs::create_dir(&put_old)?;
|
||||||
|
|
||||||
let old_root = new_root.join("old_root/");
|
// pivot the old root into a subdirectory of the new root
|
||||||
fs::create_dir(&old_root)?;
|
pivot_root(&new_root, &put_old).map_err(|e| Error::Nix {
|
||||||
|
|
||||||
pivot_root(&new_root, &old_root).map_err(|e| Error::Nix {
|
|
||||||
msg: "pivot_root",
|
msg: "pivot_root",
|
||||||
src: e,
|
src: e,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// chdir after
|
||||||
std::env::set_current_dir("/")?;
|
std::env::set_current_dir("/")?;
|
||||||
|
|
||||||
umount("old_root/").map_err(|e| Error::Nix {
|
// TODO: mount requested mounts
|
||||||
msg: "umount",
|
|
||||||
|
// unmount the old root
|
||||||
|
umount2("old_root/", MntFlags::MNT_DETACH).map_err(|e| Error::Nix {
|
||||||
|
msg: "umount2",
|
||||||
|
src: e,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// delete the old root mount point
|
||||||
|
fs::remove_dir("old_root/")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void_user_namespace(&self) -> Result<()> {
|
||||||
|
unshare(CloneFlags::CLONE_NEWUSER).map_err(|e| Error::Nix {
|
||||||
|
msg: "unshare",
|
||||||
src: e,
|
src: e,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user