summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-02-06 23:24:05 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-02-06 23:24:05 +0100
commit6f446ffc9dd49cac07e6c0096cc512e379a7f3ed (patch)
tree987240e7137a9332dab957899533ffcbe04689c7
parentad74dfb5520414b21d2e8b057f846661e671fc2e (diff)
downloadrebel-6f446ffc9dd49cac07e6c0096cc512e379a7f3ed.tar
rebel-6f446ffc9dd49cac07e6c0096cc512e379a7f3ed.zip
Unpack rootfs into tmpfs in runc namespace
-rw-r--r--Cargo.lock33
-rw-r--r--Cargo.toml1
-rw-r--r--src/runner/runc.rs4
-rw-r--r--src/runner/runc/init.rs80
-rw-r--r--src/runner/runc/run.rs18
5 files changed, 124 insertions, 12 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 29936a6..f2dfe9d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -74,6 +74,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
[[package]]
+name = "filetime"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "redox_syscall",
+ "winapi 0.3.9",
+]
+
+[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -355,6 +367,7 @@ dependencies = [
"scopeguard",
"serde",
"serde_yaml",
+ "tar",
"users",
"walkdir",
]
@@ -442,6 +455,17 @@ dependencies = [
]
[[package]]
+name = "tar"
+version = "0.4.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
+[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -557,6 +581,15 @@ dependencies = [
]
[[package]]
+name = "xattr"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index c32da16..15a8c7a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,5 +14,6 @@ nix = "0.19.1"
scopeguard = "1.1.0"
serde = { version = "1", features = ["derive"] }
serde_yaml = "0.8"
+tar = "0.4.32"
users = "0.11.0"
walkdir = "2"
diff --git a/src/runner/runc.rs b/src/runner/runc.rs
index 6a60eea..35ef1f4 100644
--- a/src/runner/runc.rs
+++ b/src/runner/runc.rs
@@ -19,7 +19,7 @@ fn runner(
init_error_sender: ipc::IpcSender<init::Error>,
channel: ipc::IpcReceiver<Request>,
) -> ! {
- if let Err(error) = init::runc_initialize() {
+ if let Err(error) = init::runc_unshare() {
init_error_sender.send(error).expect("IPC send() failed");
process::exit(1);
}
@@ -36,6 +36,8 @@ fn runner(
unistd::setgid(unistd::Gid::from_raw(0)).expect("setgid()");
unistd::setgroups(&[]).expect("setgroups()");
+ init::runc_initialize().unwrap();
+
while let Ok(request) = channel.recv() {
let Request(task, task_def, reply_sender) = request;
if let Err(error) = run::handle_task(task, task_def) {
diff --git a/src/runner/runc/init.rs b/src/runner/runc/init.rs
index 02b89e4..1786719 100644
--- a/src/runner/runc/init.rs
+++ b/src/runner/runc/init.rs
@@ -1,4 +1,10 @@
-use std::io;
+use std::{
+ ffi::CString,
+ fs::{DirBuilder, File},
+ io,
+ os::unix::ffi::OsStrExt,
+ path::Path,
+};
use nix::{
mount::{self, MsFlags},
@@ -6,7 +12,9 @@ use nix::{
};
use serde::{Deserialize, Serialize};
-fn mount_buildtmp() -> nix::Result<()> {
+use crate::util::ToIOResult;
+
+fn prepare_buildtmp() -> io::Result<()> {
mount::mount::<_, _, _, str>(
Some("buildtmp"),
"build/tmp",
@@ -14,6 +22,56 @@ fn mount_buildtmp() -> nix::Result<()> {
MsFlags::empty(),
None,
)
+ .to_io_result()?;
+
+ DirBuilder::new().create("build/tmp/rootfs")?;
+
+ {
+ let file = File::open("build/rootfs.tar")?;
+ let mut archive = tar::Archive::new(file);
+ archive.set_preserve_permissions(true);
+ archive.set_preserve_mtime(true);
+ archive.set_unpack_xattrs(true);
+
+ let dst = Path::new("build/tmp/rootfs");
+
+ for entry_r in archive.entries()? {
+ let mut entry = entry_r?;
+ if entry.unpack_in(dst)? {
+ let header = entry.header();
+ let uid = header.uid()? as libc::uid_t;
+ let gid = header.gid()? as libc::gid_t;
+
+ let path = CString::new(dst.join(entry.path()?).as_os_str().as_bytes())
+ .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
+ if unsafe { libc::lchown(path.as_ptr(), uid, gid) } < 0 {
+ return Err(io::Error::last_os_error());
+ }
+ }
+ }
+ }
+
+ DirBuilder::new().create("build/tmp/runc")?;
+ DirBuilder::new().create("build/tmp/runc/rootfs")?;
+
+ mount::mount::<_, _, str, str>(
+ Some("build/tmp/rootfs"),
+ "build/tmp/runc/rootfs",
+ None,
+ MsFlags::MS_BIND,
+ None,
+ )
+ .to_io_result()?;
+ mount::mount::<str, _, str, str>(
+ None,
+ "build/tmp/runc/rootfs",
+ None,
+ MsFlags::MS_BIND | MsFlags::MS_REMOUNT | MsFlags::MS_RDONLY,
+ None,
+ )
+ .to_io_result()?;
+
+ Ok(())
}
#[derive(Debug, Deserialize, Serialize)]
@@ -22,11 +80,11 @@ pub enum Error {
String(String),
}
-impl From<nix::Error> for Error {
- fn from(error: nix::Error) -> Self {
- match error {
- nix::Error::Sys(code) => Error::Code(code as i32),
- _ => Error::String(error.to_string()),
+impl From<io::Error> for Error {
+ fn from(error: io::Error) -> Self {
+ match error.raw_os_error() {
+ Some(code) => Error::Code(code),
+ None => Error::String(error.to_string()),
}
}
}
@@ -40,8 +98,12 @@ impl From<Error> for io::Error {
}
}
+pub fn runc_unshare() -> Result<(), Error> {
+ sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS).to_io_result()?;
+ Ok(())
+}
+
pub fn runc_initialize() -> Result<(), Error> {
- sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS)?;
- mount_buildtmp()?;
+ prepare_buildtmp()?;
Ok(())
}
diff --git a/src/runner/runc/run.rs b/src/runner/runc/run.rs
index 2d13330..9261b7d 100644
--- a/src/runner/runc/run.rs
+++ b/src/runner/runc/run.rs
@@ -1,4 +1,4 @@
-use std::io;
+use std::{io, process};
use serde::{Deserialize, Serialize};
@@ -13,6 +13,20 @@ impl From<Error> for io::Error {
}
pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> {
- println!("{}:\n\t{:?}", task, task_def);
+ let result = process::Command::new("sh")
+ .arg("-c")
+ .arg(task_def.run)
+ .current_dir("build/tmp/runc/rootfs")
+ .output();
+ if let Ok(output) = result {
+ println!(
+ "{}:\n{}",
+ task,
+ String::from_utf8_lossy(output.stdout.as_slice()),
+ );
+ } else {
+ println!("{}:\n\t{:?}", task, result);
+ }
+
Ok(())
}