From 8da7dfadf4581dcd6bb8a042024df7f3fbaf9cea Mon Sep 17 00:00:00 2001 From: Emil Engler Date: Tue, 21 Feb 2023 16:52:07 +0100 Subject: [PATCH] hypervisor: support user space mounts This commit introduces the ability to mount custom files and folders from the host operating system onto a partition. The hypervisor configuration is adjusted as follows at partition layer: ```yaml mounts: - [ "/dev/urandom", "/dev/urandom"] - [ "/dev/urandom", "/dev/random"] - [ "/a/file/on/the/host", "/guest" ] ``` Future features could additionally include the ability to mount things read-only, etc. Fixes #42 --- hypervisor/src/hypervisor/config.rs | 2 ++ hypervisor/src/hypervisor/partition.rs | 42 ++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/hypervisor/src/hypervisor/config.rs b/hypervisor/src/hypervisor/config.rs index 4fd0f22..1ec5ed9 100644 --- a/hypervisor/src/hypervisor/config.rs +++ b/hypervisor/src/hypervisor/config.rs @@ -38,6 +38,8 @@ pub struct Partition { pub devices: Vec, #[serde(default)] pub hm_table: PartitionHMTable, + #[serde(default)] + pub mounts: Vec<(PathBuf, PathBuf)>, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/hypervisor/src/hypervisor/partition.rs b/hypervisor/src/hypervisor/partition.rs index bc76435..02a4168 100644 --- a/hypervisor/src/hypervisor/partition.rs +++ b/hypervisor/src/hypervisor/partition.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::time::Duration; -use anyhow::anyhow; +use anyhow::{anyhow, bail}; use apex_rs::bindings::PortDirection; use apex_rs::prelude::{OperatingMode, StartCondition}; use clone3::Clone3; @@ -99,6 +99,36 @@ impl FileMounter { } } +impl TryFrom<&(PathBuf, PathBuf)> for FileMounter { + type Error = anyhow::Error; + + fn try_from(paths: &(PathBuf, PathBuf)) -> Result { + let source = &paths.0; + let mut target = paths.1.clone(); + + if !source.exists() { + bail!("File/Directory {} not existent", source.display()) + } + + if target.is_absolute() { + // Convert absolute paths into relative ones. + // Otherwise we will receive a permission error. + // TODO: Make this a function? + target = target.strip_prefix("/")?.into(); + assert!(target.is_relative()); + } + + Ok(Self { + source: Some(source.clone()), + target: target, + fstype: None, + flags: MsFlags::MS_BIND, + data: None, + is_dir: source.is_dir(), + }) + } +} + impl Run { pub fn new(base: &Base, condition: StartCondition, warm_start: bool) -> TypedResult { trace!("Create new \"Run\" for \"{}\" partition", base.name()); @@ -175,7 +205,7 @@ impl Run { Partition::release_fds(&keep).unwrap(); // Mount the required mounts - let mounts = [ + let mut mounts = vec![ // Mount working directory as tmpfs FileMounter { source: None, @@ -223,6 +253,12 @@ impl Run { }, ]; + for m in &base.mounts { + mounts.push(m.try_into().unwrap()); + } + + // TODO: Check for duplicate mounts + for m in mounts { debug!("mounting {:?}", &m); m.mount(base.working_dir.path()).unwrap(); @@ -450,6 +486,7 @@ pub(crate) struct Base { hm: PartitionHMTable, id: i64, bin: PathBuf, + mounts: Vec<(PathBuf, PathBuf)>, cgroup: CGroup, sampling_channel: HashMap, duration: Duration, @@ -518,6 +555,7 @@ impl Partition { id: config.id, cgroup, bin: config.image, + mounts: config.mounts, duration: config.duration, period: config.period, working_dir,