summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-10-20 00:20:35 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-10-20 22:14:14 +0200
commit1abff00386b5d30f27899810799ace7eb4fb12c0 (patch)
treeb914c8b4319a906d2165c4fef2a7d7f8d96052b4 /src
parentecf908c54f55d49b36f5068e1acc95a7d687e626 (diff)
downloadrebel-1abff00386b5d30f27899810799ace7eb4fb12c0.tar
rebel-1abff00386b5d30f27899810799ace7eb4fb12c0.zip
container: tar: run without crun
Set up a new mount namespace, so we can mount over the shared rootfs. Replace crun with a simple chrooted exec.
Diffstat (limited to 'src')
-rw-r--r--src/runner/container/tar.rs99
-rw-r--r--src/runner/container/task.rs4
-rw-r--r--src/util/fs.rs10
3 files changed, 65 insertions, 48 deletions
diff --git a/src/runner/container/tar.rs b/src/runner/container/tar.rs
index 67993c1..5800aa0 100644
--- a/src/runner/container/tar.rs
+++ b/src/runner/container/tar.rs
@@ -1,67 +1,76 @@
use std::{
+ fs::File,
io::{self, Read, Write},
+ os::unix::prelude::CommandExt,
path::Path,
- process,
+ process::{self, Command, Stdio},
};
-use nix::mount::MsFlags;
+use nix::{
+ mount::{self, MsFlags},
+ sched::CloneFlags,
+ sys::wait,
+ unistd,
+};
use crate::{
paths,
- types::InputHash,
util::{error::*, fs, Checkable},
};
-use super::spec;
+use super::ns;
-pub fn pack<W: Write, P: AsRef<Path>>(
- input_hash: &InputHash,
- archive: &mut W,
- source: P,
-) -> Result<()> {
- let task_tmp_dir = paths::task_tmp_dir(input_hash);
+pub fn pack<W: Write, P: AsRef<Path>>(archive: &mut W, source: P) -> Result<()> {
+ let (mut piper, pipew) = fs::pipe()?;
- let rootfs_mount_target = paths::join(&[&task_tmp_dir, paths::TASK_TMP_ROOTFS_SUBDIR]);
- let _rootfs_mount = fs::mount(
- paths::ROOTFS_DIR,
- &rootfs_mount_target,
- None,
- MsFlags::MS_BIND,
- None,
- )?;
+ let exec_tar = |stdout: File| -> Result<()> {
+ // We are in our own mount namespace, so mounting into the shared ROOTFS_DIR is fine
+ let mount_target = paths::join(&[paths::ROOTFS_DIR, paths::TASK_BUILDDIR]);
+ mount::mount::<_, _, str, str>(
+ Some(source.as_ref()),
+ mount_target.as_str(),
+ None,
+ MsFlags::MS_BIND,
+ None,
+ )?;
- let source_mount_target = paths::join(&[&task_tmp_dir, paths::TASK_WORKDIR]);
- let _source_mount = fs::mount(source, &source_mount_target, None, MsFlags::MS_BIND, None)?;
+ unistd::chroot(paths::ROOTFS_DIR).context("chroot()")?;
+ unistd::chdir(paths::abs(paths::TASK_BUILDDIR).as_str()).context("chdir()")?;
- spec::generate_spec(&[
- "tar",
- "-c",
- "--sort=name",
- "--numeric-owner",
- "--owner=0",
- "--group=0",
- "--mtime=@0",
- ".",
- ])
- .save(paths::join(&[&task_tmp_dir, "config.json"]))
- .map_err(Error::new)
- .context("Failed to save runtime config")?;
+ let err = Command::new("tar")
+ .args(&[
+ "-c",
+ "--sort=name",
+ "--numeric-owner",
+ "--owner=0",
+ "--group=0",
+ "--mtime=@0",
+ ".",
+ ])
+ .stdin(Stdio::null())
+ .stdout(stdout)
+ .env_clear()
+ .env("PATH", "/usr/sbin:/usr/bin:/sbin:/bin")
+ .exec();
+ eprintln!("{}", err);
+ process::exit(127);
+ };
- let mut child = process::Command::new("crun")
- .arg("--root")
- .arg(paths::TASK_TMP_CONTAINERS_ROOT_SUBDIR)
- .arg("run")
- .arg(input_hash.to_string())
- .current_dir(task_tmp_dir)
- .stdin(process::Stdio::null())
- .stdout(process::Stdio::piped())
- .spawn()
- .context("Failed to start container runtime")?;
+ let (pid, pipew) = unsafe {
+ ns::spawn(CloneFlags::CLONE_NEWNS, pipew, |pipew| {
+ exec_tar(pipew).unwrap()
+ })
+ }
+ .context("Failed to run tar")?;
- io::copy(&mut child.stdout.take().unwrap(), archive).context("Failed to write TAR archive")?;
+ drop(pipew);
+ let result = io::copy(&mut piper, archive).context("Failed to write TAR archive");
- child.wait()?.check()?;
+ wait::waitpid(pid, None)?
+ .check()
+ .context("tar did not exit successfully")?;
+ result?;
Ok(())
}
diff --git a/src/runner/container/task.rs b/src/runner/container/task.rs
index b6b8026..73d0d64 100644
--- a/src/runner/container/task.rs
+++ b/src/runner/container/task.rs
@@ -167,7 +167,7 @@ fn collect_output(input_hash: &InputHash, path: &str) -> Result<Option<ArchiveHa
let writer = TeeWriter::new(file, hasher);
let mut buffered_writer = BufWriter::with_capacity(16 * 1024 * 1024, writer);
- super::tar::pack(input_hash, &mut buffered_writer, &source)?;
+ super::tar::pack(&mut buffered_writer, &source)?;
let writer = buffered_writer.into_inner()?;
let (file, hasher) = writer.into_inner();
@@ -271,7 +271,7 @@ fn hash_layer(input_hash: &InputHash) -> Result<Option<LayerHash>> {
let hasher = LayerHasher::new();
let mut buffered_writer = BufWriter::with_capacity(16 * 1024 * 1024, hasher);
- tar::pack(input_hash, &mut buffered_writer, &task_layer_dir)?;
+ tar::pack(&mut buffered_writer, &task_layer_dir)?;
let hasher = buffered_writer.into_inner()?;
Ok(Some(LayerHash(StringHash(hasher.finalize().into()))))
diff --git a/src/util/fs.rs b/src/util/fs.rs
index 9344c72..cfc7610 100644
--- a/src/util/fs.rs
+++ b/src/util/fs.rs
@@ -1,10 +1,12 @@
use std::{
- fs, io,
+ fs::{self, File},
+ io,
os::unix::prelude::*,
path::{Path, PathBuf},
};
use nix::{
+ fcntl::OFlag,
mount::{self, MsFlags},
unistd,
};
@@ -112,3 +114,9 @@ pub fn mount<P1: AsRef<Path>, P2: AsRef<Path>>(
.with_context(|| format!("Failed to mount {:?}", canon_target))?;
Ok(Mount(canon_target))
}
+
+pub fn pipe() -> Result<(File, File)> {
+ unistd::pipe2(OFlag::O_CLOEXEC)
+ .context("pipe2()")
+ .map(|(piper, pipew)| unsafe { (File::from_raw_fd(piper), File::from_raw_fd(pipew)) })
+}