Skip to content

Commit 870da02

Browse files
cgwaltersjeckersb
authored andcommitted
Split out a hostexec module
We'll use this even in cases where we don't have the `install` feature. Signed-off-by: Colin Walters <[email protected]>
1 parent 0e4f7ec commit 870da02

File tree

6 files changed

+43
-34
lines changed

6 files changed

+43
-34
lines changed

lib/src/blockdev.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use nix::errno::Errno;
1313
use regex::Regex;
1414
use serde::Deserialize;
1515

16-
use crate::install::run_in_host_mountns;
16+
use crate::hostexec::run_in_host_mountns;
1717
use crate::task::Task;
1818

1919
#[derive(Debug, Deserialize)]

lib/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
799799
},
800800
#[cfg(feature = "install")]
801801
Opt::ExecInHostMountNamespace { args } => {
802-
crate::install::exec_in_host_mountns(args.as_slice())
802+
crate::hostexec::exec_in_host_mountns(args.as_slice())
803803
}
804804
Opt::Status(opts) => super::status::status(opts).await,
805805
Opt::Internals(opts) => match opts {

lib/src/hostexec.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//! Run a command in the host mount namespace
2+
3+
use std::os::fd::AsFd;
4+
use std::os::unix::process::CommandExt;
5+
use std::process::Command;
6+
7+
use anyhow::{Context, Result};
8+
use camino::Utf8Path;
9+
use fn_error_context::context;
10+
11+
/// Run a command in the host mount namespace
12+
pub(crate) fn run_in_host_mountns(cmd: &str) -> Command {
13+
let mut c = Command::new("/proc/self/exe");
14+
c.args(["exec-in-host-mount-namespace", cmd]);
15+
c
16+
}
17+
18+
#[context("Re-exec in host mountns")]
19+
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
20+
let (cmd, args) = args
21+
.split_first()
22+
.ok_or_else(|| anyhow::anyhow!("Missing command"))?;
23+
tracing::trace!("{cmd:?} {args:?}");
24+
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
25+
nix::sched::setns(pid1mountns.as_fd(), nix::sched::CloneFlags::CLONE_NEWNS).context("setns")?;
26+
rustix::process::chdir("/").context("chdir")?;
27+
// Work around supermin doing chroot() and not pivot_root
28+
// https://github.com/libguestfs/supermin/blob/5230e2c3cd07e82bd6431e871e239f7056bf25ad/init/init.c#L288
29+
if !Utf8Path::new("/usr").try_exists().context("/usr")?
30+
&& Utf8Path::new("/root/usr")
31+
.try_exists()
32+
.context("/root/usr")?
33+
{
34+
tracing::debug!("Using supermin workaround");
35+
rustix::process::chroot("/root").context("chroot")?;
36+
}
37+
Err(Command::new(cmd).args(args).exec()).context("exec")?
38+
}

lib/src/install.rs

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ pub(crate) mod osconfig;
1212

1313
use std::io::Write;
1414
use std::os::fd::AsFd;
15-
use std::os::unix::process::CommandExt;
1615
use std::path::Path;
17-
use std::process::Command;
1816
use std::str::FromStr;
1917
use std::sync::Arc;
2018
use std::time::Duration;
@@ -39,6 +37,7 @@ use serde::{Deserialize, Serialize};
3937

4038
use self::baseline::InstallBlockDeviceOpts;
4139
use crate::containerenv::ContainerExecutionInfo;
40+
use crate::hostexec::run_in_host_mountns;
4241
use crate::mount::Filesystem;
4342
use crate::task::Task;
4443
use crate::utils::sigpolicy_from_opts;
@@ -755,35 +754,6 @@ async fn initialize_ostree_root_from_self(
755754
Ok(aleph)
756755
}
757756

758-
/// Run a command in the host mount namespace
759-
pub(crate) fn run_in_host_mountns(cmd: &str) -> Command {
760-
let mut c = Command::new("/proc/self/exe");
761-
c.args(["exec-in-host-mount-namespace", cmd]);
762-
c
763-
}
764-
765-
#[context("Re-exec in host mountns")]
766-
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
767-
let (cmd, args) = args
768-
.split_first()
769-
.ok_or_else(|| anyhow::anyhow!("Missing command"))?;
770-
tracing::trace!("{cmd:?} {args:?}");
771-
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
772-
nix::sched::setns(pid1mountns.as_fd(), nix::sched::CloneFlags::CLONE_NEWNS).context("setns")?;
773-
rustix::process::chdir("/").context("chdir")?;
774-
// Work around supermin doing chroot() and not pivot_root
775-
// https://github.com/libguestfs/supermin/blob/5230e2c3cd07e82bd6431e871e239f7056bf25ad/init/init.c#L288
776-
if !Utf8Path::new("/usr").try_exists().context("/usr")?
777-
&& Utf8Path::new("/root/usr")
778-
.try_exists()
779-
.context("/root/usr")?
780-
{
781-
tracing::debug!("Using supermin workaround");
782-
rustix::process::chroot("/root").context("chroot")?;
783-
}
784-
Err(Command::new(cmd).args(args).exec()).context("exec")?
785-
}
786-
787757
#[context("Querying skopeo version")]
788758
fn require_skopeo_with_containers_storage() -> Result<()> {
789759
let out = Task::new_cmd("skopeo --version", run_in_host_mountns("skopeo"))

lib/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
pub mod cli;
2121
pub(crate) mod deploy;
2222
pub(crate) mod generator;
23+
pub(crate) mod hostexec;
2324
mod image;
2425
pub(crate) mod journal;
2526
pub(crate) mod kargs;

lib/src/podman.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::{anyhow, Result};
22
use serde::Deserialize;
33

4-
use crate::install::run_in_host_mountns;
4+
use crate::hostexec::run_in_host_mountns;
55
use crate::task::Task;
66

77
/// Where we look inside our container to find our own image

0 commit comments

Comments
 (0)