summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hasher.rs54
-rw-r--r--src/initramfs.rs27
2 files changed, 79 insertions, 2 deletions
diff --git a/src/hasher.rs b/src/hasher.rs
index da00778..f2bf378 100644
--- a/src/hasher.rs
+++ b/src/hasher.rs
@@ -1,4 +1,5 @@
use std::ffi::OsString;
+use std::path::Path;
use std::process::Command;
use anyhow::{Context, Result, bail};
@@ -54,6 +55,59 @@ impl CommandRunner for ProcessRunner {
}
}
+/// Runs Hasher commands under the configured non-root Hasher account.
+/// Root retains ownership of native rootfs finalization and packaging stages.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct SudoUserRunner {
+ user: OsString,
+}
+
+impl SudoUserRunner {
+ pub fn new(user: impl Into<OsString>) -> Self {
+ Self { user: user.into() }
+ }
+
+ pub fn wrap(&self, invocation: Invocation) -> Invocation {
+ let mut arguments = vec![
+ OsString::from("-n"),
+ OsString::from("-u"),
+ self.user.clone(),
+ ];
+ arguments.push(invocation.program);
+ arguments.extend(invocation.arguments);
+ Invocation::new("sudo", arguments)
+ }
+
+ pub fn prepare_workdir(&self, workdir: &Path) -> Invocation {
+ Invocation::new(
+ "sudo",
+ [
+ "-n".into(),
+ "install".into(),
+ "-d".into(),
+ "-o".into(),
+ self.user.clone(),
+ "-g".into(),
+ self.user.clone(),
+ workdir.as_os_str().to_owned(),
+ ],
+ )
+ }
+}
+
+impl CommandRunner for SudoUserRunner {
+ fn run(&self, invocation: Invocation) -> Result<()> {
+ if let Some(workdir) = invocation
+ .arguments()
+ .windows(2)
+ .find_map(|pair| (pair[0] == "--workdir").then(|| Path::new(&pair[1])))
+ {
+ ProcessRunner.run(self.prepare_workdir(workdir))?;
+ }
+ ProcessRunner.run(self.wrap(invocation))
+ }
+}
+
#[derive(Debug)]
pub struct HasherInstaller<R> {
runner: R,
diff --git a/src/initramfs.rs b/src/initramfs.rs
index 4ece24c..c934aaf 100644
--- a/src/initramfs.rs
+++ b/src/initramfs.rs
@@ -93,6 +93,7 @@ fn normalize(
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InitramfsRequest {
rootfs: PathBuf,
+ hasher_workdir: Option<PathBuf>,
kernel: KernelVersion,
}
@@ -102,12 +103,18 @@ impl InitramfsRequest {
if !rootfs.is_dir() {
bail!("rootfs is not a directory: {}", rootfs.display());
}
+ let hasher_workdir = rootfs.parent().map(Path::to_path_buf);
Ok(Self {
rootfs: rootfs.to_path_buf(),
+ hasher_workdir,
kernel: KernelVersion::discover_rt(rootfs)?,
})
}
+ pub fn hasher_workdir(&self) -> Option<&Path> {
+ self.hasher_workdir.as_deref()
+ }
+
pub fn rootfs(&self) -> &Path {
&self.rootfs
}
@@ -179,13 +186,29 @@ impl<R> MakeInitrdBuilder<R> {
impl<R: CommandRunner> InitramfsBuilder for MakeInitrdBuilder<R> {
fn build(&mut self, request: &InitramfsRequest) -> Result<InitramfsResult> {
+ let workdir = request
+ .hasher_workdir()
+ .ok_or_else(|| anyhow::anyhow!("rootfs has no Hasher workdir parent"))?;
self.runner.run(Invocation::new(
- "chroot",
+ "sudo",
[
- request.rootfs().as_os_str().to_owned(),
+ "-n".into(),
+ "-u".into(),
+ "hermes".into(),
+ "hsh-run".into(),
+ "--rooter".into(),
+ "--mountpoints=/proc".into(),
+ "--workdir".into(),
+ workdir.as_os_str().to_owned(),
+ "--".into(),
"make-initrd".into(),
+ "-N".into(),
+ "-v".into(),
"-k".into(),
request.kernel().as_str().into(),
+ "AUTODETECT=".into(),
+ "-c".into(),
+ "/etc/initrd.mk.oem".into(),
],
))?;
let result = InitramfsResult::from_rootfs(request.rootfs(), request.kernel())?;