diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/hasher.rs | 54 | ||||
| -rw-r--r-- | src/initramfs.rs | 27 |
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())?; |