summaryrefslogtreecommitdiffstats
path: root/src
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 /src
parentad74dfb5520414b21d2e8b057f846661e671fc2e (diff)
downloadrebel-6f446ffc9dd49cac07e6c0096cc512e379a7f3ed.tar
rebel-6f446ffc9dd49cac07e6c0096cc512e379a7f3ed.zip
Unpack rootfs into tmpfs in runc namespace
Diffstat (limited to 'src')
-rw-r--r--src/runner/runc.rs4
-rw-r--r--src/runner/runc/init.rs80
-rw-r--r--src/runner/runc/run.rs18
3 files changed, 90 insertions, 12 deletions
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(())
}