From e3119a77bfe4be98b721dfe262b01e2c328c3c79 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 30 Oct 2021 23:40:08 +0200 Subject: runner: set up /dev in separate directory Preparation for removal of a single rootfs. --- crates/runner/src/init.rs | 33 +++++++++++++++++++++++++-------- crates/runner/src/paths.rs | 2 ++ crates/runner/src/tar.rs | 8 ++++++++ crates/runner/src/task.rs | 2 +- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/crates/runner/src/init.rs b/crates/runner/src/init.rs index 07631ea..ad37cf0 100644 --- a/crates/runner/src/init.rs +++ b/crates/runner/src/init.rs @@ -7,15 +7,31 @@ use common::error::*; use super::{tar, util::fs}; use crate::paths; -fn prepare_rootfs(rootfs: &str) -> Result<()> { - tar::unpack(File::open(paths::ROOTFS_ARCHIVE)?, rootfs) +fn prepare_rootfs(path: &str) -> Result<()> { + tar::unpack(File::open(paths::ROOTFS_ARCHIVE)?, path) .context("Unpacking build container rootfs failed")?; - mount::mount::<_, _, str, str>(Some(rootfs), rootfs, None, MsFlags::MS_BIND, None) + mount::mount::<_, _, str, str>(Some(path), path, None, MsFlags::MS_BIND, None) .context("Failed to bind mount container rootfs")?; + mount::mount::( + None, + path, + None, + MsFlags::MS_REMOUNT | MsFlags::MS_BIND | MsFlags::MS_RDONLY, + None, + ) + .context("Failed to mount container rootfs read-only")?; + + Ok(()) +} + +fn prepare_dev(path: &str) -> Result<()> { + fs::mkdir(path)?; + mount::mount::<_, _, str, str>(Some(path), path, None, MsFlags::MS_BIND, None) + .context("Failed to bind mount container /dev")?; for dir in ["pts", "shm"] { - fs::mkdir(paths::join(&[rootfs, "dev", dir]))?; + fs::mkdir(paths::join(&[path, dir]))?; } for (link, target) in [ @@ -25,14 +41,14 @@ fn prepare_rootfs(rootfs: &str) -> Result<()> { ("stderr", "/proc/self/fd/2"), ("ptmx", "pts/ptmx"), ] { - let path = paths::join(&[rootfs, "dev", link]); + let path = paths::join(&[path, link]); std::os::unix::fs::symlink(target, &path) .with_context(|| format!("Failed to create link {}", path))?; } for dev in ["null", "zero", "full", "random", "urandom", "tty"] { let source = paths::join(&["/dev", dev]); - let target = paths::join(&[rootfs, "dev", dev]); + let target = paths::join(&[path, dev]); fs::create(&target)?; mount::mount::(Some(&source), &target, None, MsFlags::MS_BIND, None) .with_context(|| format!("Failed to bind mount {}", source))?; @@ -40,12 +56,12 @@ fn prepare_rootfs(rootfs: &str) -> Result<()> { mount::mount::( None, - rootfs, + path, None, MsFlags::MS_REMOUNT | MsFlags::MS_BIND | MsFlags::MS_RDONLY, None, ) - .context("Failed to mount container rootfs read-only")?; + .context("Failed to mount container /dev read-only")?; Ok(()) } @@ -68,6 +84,7 @@ pub fn init_runner() -> Result<()> { .context("Failed to set MS_PRIVATE for build tmpdir")?; prepare_rootfs(paths::ROOTFS_DIR)?; + prepare_dev(paths::DEV_DIR)?; Ok(()) } diff --git a/crates/runner/src/paths.rs b/crates/runner/src/paths.rs index ac0d758..5e183cb 100644 --- a/crates/runner/src/paths.rs +++ b/crates/runner/src/paths.rs @@ -26,6 +26,7 @@ //! │ │ └── task.lock # task lockfile //! │   └── ... //! └── tmp/ # temporary files (cleaned on start) +//!    ├── dev/ # container /dev //!    ├── rootfs/ # unpacked rootfs.tar //!    └── task/ //!    └── / @@ -44,6 +45,7 @@ pub const ROOTFS_ARCHIVE: &str = "build/rootfs.tar"; pub const DOWNLOADS_DIR: &str = "build/downloads"; pub const TMP_DIR: &str = "build/tmp"; +pub const DEV_DIR: &str = "build/tmp/dev"; pub const ROOTFS_DIR: &str = "build/tmp/rootfs"; pub const TASK_TMP_DIR: &str = "build/tmp/task"; diff --git a/crates/runner/src/tar.rs b/crates/runner/src/tar.rs index 3fd21e7..32d8e8d 100644 --- a/crates/runner/src/tar.rs +++ b/crates/runner/src/tar.rs @@ -24,6 +24,14 @@ pub fn pack>(archive: &mut W, source: P) -> Result<()> let exec_tar = || -> Result<()> { // We are in our own mount namespace, so mounting into the shared ROOTFS_DIR is fine + let dev_target = paths::join(&[paths::ROOTFS_DIR, "dev"]); + mount::mount::<_, _, str, str>( + Some(paths::DEV_DIR), + dev_target.as_str(), + None, + MsFlags::MS_BIND | MsFlags::MS_REC, + None, + )?; let mount_target = paths::join(&[paths::ROOTFS_DIR, paths::TASK_BUILDDIR]); mount::mount::<_, _, str, str>( Some(source.as_ref()), diff --git a/crates/runner/src/task.rs b/crates/runner/src/task.rs index 8761eb2..5d3f664 100644 --- a/crates/runner/src/task.rs +++ b/crates/runner/src/task.rs @@ -294,7 +294,7 @@ fn run_task(input_hash: &InputHash, task: &Task, jobserver: &mut Jobserver) -> R .context("Failed to duplicate log file descriptor")?; mount::mount::<_, _, str, str>( - Some(paths::join(&[paths::ROOTFS_DIR, "dev"]).as_str()), + Some(paths::DEV_DIR), paths::join(&[&rootfs, "dev"]).as_str(), None, MsFlags::MS_BIND | MsFlags::MS_REC, -- cgit v1.2.3