diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-06-19 14:43:48 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-06-19 14:43:48 +0200 |
commit | 1fa0de5175075a841e24925f76fc472927a5308d (patch) | |
tree | 12a4654c9c728000093605eaedc1a043a02debe0 | |
parent | 512c44489c9582c40f04b8dfcdc5068c62589001 (diff) | |
download | rebel-1fa0de5175075a841e24925f76fc472927a5308d.tar rebel-1fa0de5175075a841e24925f76fc472927a5308d.zip |
Collect task output to tar files
-rw-r--r-- | examples/foo.yml | 3 | ||||
-rw-r--r-- | src/runner/runc.rs | 4 | ||||
-rw-r--r-- | src/runner/runc/init.rs | 5 | ||||
-rw-r--r-- | src/runner/runc/run.rs | 32 | ||||
-rw-r--r-- | src/util.rs | 30 | ||||
-rw-r--r-- | src/util/tar.rs | 23 |
6 files changed, 88 insertions, 9 deletions
diff --git a/examples/foo.yml b/examples/foo.yml index e0ded83..6f60bbb 100644 --- a/examples/foo.yml +++ b/examples/foo.yml @@ -5,4 +5,5 @@ tasks: run: | ls -lha ls -lha /proc/self/fd - echo foo > foo + mkdir foo + echo foobar > foo/bar diff --git a/src/runner/runc.rs b/src/runner/runc.rs index 62a3bf1..938bab0 100644 --- a/src/runner/runc.rs +++ b/src/runner/runc.rs @@ -20,7 +20,7 @@ fn runner( init_error_sender: ipc::IpcSender<init::Error>, channel: ipc::IpcReceiver<Request>, ) -> ! { - if let Err(error) = init::runc_unshare() { + if let Err(error) = init::runc_preinit() { init_error_sender.send(error).expect("IPC send() failed"); process::exit(1); } @@ -37,7 +37,7 @@ fn runner( unistd::setgid(unistd::Gid::from_raw(0)).expect("setgid()"); unistd::setgroups(&[]).expect("setgroups()"); - init::runc_initialize().unwrap(); + init::runc_init().unwrap(); unsafe { signal::signal(signal::Signal::SIGCHLD, signal::SigHandler::SigIgn) }.unwrap(); diff --git a/src/runner/runc/init.rs b/src/runner/runc/init.rs index e574789..f686e3e 100644 --- a/src/runner/runc/init.rs +++ b/src/runner/runc/init.rs @@ -51,12 +51,13 @@ impl From<Error> for io::Error { } } -pub fn runc_unshare() -> Result<(), Error> { +pub fn runc_preinit() -> Result<(), Error> { + DirBuilder::new().recursive(true).create("build/state")?; sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS).to_io_result()?; Ok(()) } -pub fn runc_initialize() -> Result<(), Error> { +pub fn runc_init() -> Result<(), Error> { prepare_buildtmp()?; Ok(()) } diff --git a/src/runner/runc/run.rs b/src/runner/runc/run.rs index 7e9a41c..09bd875 100644 --- a/src/runner/runc/run.rs +++ b/src/runner/runc/run.rs @@ -1,4 +1,9 @@ -use std::{fs::DirBuilder, io, process}; +use std::{ + fs::{DirBuilder, File}, + io, + path::{Path, PathBuf}, + process, +}; use nix::{ mount::{self, MsFlags}, @@ -7,7 +12,11 @@ use nix::{ }; use serde::{Deserialize, Serialize}; -use crate::{types::*, unshare, util::ToIOResult}; +use crate::{ + types::*, + unshare, + util::{self, ToIOResult}, +}; use super::spec; @@ -59,6 +68,23 @@ fn init_task() -> Result<(), Error> { Ok(()) } +fn output_filename(task: TaskRef) -> PathBuf { + Path::new("build/state").join(format!("{}.tar", task)) +} + +fn collect_output(task: TaskRef, task_def: Task) -> Result<(), io::Error> { + // Temporarily switch to the user running Rebel to get the right + // owner for the tar files + let file = { + let _setegid = util::setegid(unistd::Gid::from_raw(unshare::BUILD_GID))?; + let _seteuid = util::seteuid(unistd::Uid::from_raw(unshare::BUILD_UID))?; + + File::create(output_filename(task))? + }; + + util::tar::pack(file, "build/tmp/runc/workdir", task_def.output.iter())?.sync_all() +} + pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> { init_task()?; @@ -89,5 +115,7 @@ pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> { String::from_utf8_lossy(output.stdout.as_slice()), ); + collect_output(task, task_def)?; + Ok(()) } diff --git a/src/util.rs b/src/util.rs index f5bbfaa..d388a59 100644 --- a/src/util.rs +++ b/src/util.rs @@ -7,7 +7,7 @@ use std::{ }; use ipc_channel::ipc; -use nix::sys::wait; +use nix::{sys::wait, unistd}; pub trait ToIOResult<T> { fn to_io_result(self) -> Result<T>; @@ -68,3 +68,31 @@ impl<T> CheckDisconnect for result::Result<T, ipc::IpcError> { } } } + +pub struct SetEUID(unistd::Uid); + +impl Drop for SetEUID { + fn drop(&mut self) { + unistd::seteuid(self.0).expect("failed to reset effective UID"); + } +} + +pub fn seteuid(uid: unistd::Uid) -> Result<SetEUID> { + let old_uid = unistd::geteuid(); + unistd::seteuid(uid).to_io_result()?; + Ok(SetEUID(old_uid)) +} + +pub struct SetEGID(unistd::Gid); + +impl Drop for SetEGID { + fn drop(&mut self) { + unistd::setegid(self.0).expect("failed to reset effective GID"); + } +} + +pub fn setegid(gid: unistd::Gid) -> Result<SetEGID> { + let old_gid = unistd::getegid(); + unistd::setegid(gid).to_io_result()?; + Ok(SetEGID(old_gid)) +} diff --git a/src/util/tar.rs b/src/util/tar.rs index 07ad795..885663e 100644 --- a/src/util/tar.rs +++ b/src/util/tar.rs @@ -1,11 +1,32 @@ use std::{ ffi::CString, fs::DirBuilder, - io::{self, Read}, + io::{self, Read, Write}, os::unix::ffi::OsStrExt, path::Path, }; +pub fn pack<W: Write, P: AsRef<Path>, E: AsRef<Path>, I: Iterator<Item = E>>( + archive: W, + source: P, + entries: I, +) -> io::Result<W> { + let mut ar = tar::Builder::new(archive); + ar.mode(tar::HeaderMode::Deterministic); + ar.follow_symlinks(false); + + for entry in entries { + let path = source.as_ref().join(entry.as_ref()); + if path.is_dir() { + ar.append_dir_all(entry.as_ref(), path)?; + } else { + ar.append_path_with_name(path, entry.as_ref())?; + } + } + + ar.into_inner() +} + pub fn unpack<R: Read, P: AsRef<Path>>(archive: R, dest: P) -> io::Result<()> { let dest_path = dest.as_ref(); |