Skip to content

Commit

Permalink
Split out a hostexec module
Browse files Browse the repository at this point in the history
We'll use this even in cases where we don't have the `install`
feature.

Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters authored and jeckersb committed Mar 28, 2024
1 parent 1707bdd commit e835d97
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 34 deletions.
2 changes: 1 addition & 1 deletion lib/src/blockdev.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::install::run_in_host_mountns;
use crate::hostexec::run_in_host_mountns;
use crate::task::Task;
use anyhow::{anyhow, Context, Result};
use camino::{Utf8Path, Utf8PathBuf};
Expand Down
2 changes: 1 addition & 1 deletion lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
},
#[cfg(feature = "install")]
Opt::ExecInHostMountNamespace { args } => {
crate::install::exec_in_host_mountns(args.as_slice())
crate::hostexec::exec_in_host_mountns(args.as_slice())
}
Opt::Status(opts) => super::status::status(opts).await,
Opt::Internals(opts) => match opts {
Expand Down
38 changes: 38 additions & 0 deletions lib/src/hostexec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! Run a command in the host mount namespace
use std::os::fd::AsFd;
use std::os::unix::process::CommandExt;
use std::process::Command;

use anyhow::{Context, Result};
use camino::Utf8Path;
use fn_error_context::context;

/// Run a command in the host mount namespace
pub(crate) fn run_in_host_mountns(cmd: &str) -> Command {
let mut c = Command::new("/proc/self/exe");
c.args(["exec-in-host-mount-namespace", cmd]);
c
}

#[context("Re-exec in host mountns")]
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
let (cmd, args) = args
.split_first()
.ok_or_else(|| anyhow::anyhow!("Missing command"))?;
tracing::trace!("{cmd:?} {args:?}");
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
nix::sched::setns(pid1mountns.as_fd(), nix::sched::CloneFlags::CLONE_NEWNS).context("setns")?;
rustix::process::chdir("/").context("chdir")?;
// Work around supermin doing chroot() and not pivot_root
// https://github.com/libguestfs/supermin/blob/5230e2c3cd07e82bd6431e871e239f7056bf25ad/init/init.c#L288
if !Utf8Path::new("/usr").try_exists().context("/usr")?
&& Utf8Path::new("/root/usr")
.try_exists()
.context("/root/usr")?
{
tracing::debug!("Using supermin workaround");
rustix::process::chroot("/root").context("chroot")?;
}
Err(Command::new(cmd).args(args).exec()).context("exec")?
}
32 changes: 1 addition & 31 deletions lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ pub(crate) mod osconfig;

use std::io::Write;
use std::os::fd::AsFd;
use std::os::unix::process::CommandExt;
use std::path::Path;
use std::process::Command;
use std::str::FromStr;
use std::sync::Arc;

Expand All @@ -39,6 +37,7 @@ use serde::{Deserialize, Serialize};

use self::baseline::InstallBlockDeviceOpts;
use crate::containerenv::ContainerExecutionInfo;
use crate::hostexec::run_in_host_mountns;
use crate::mount::Filesystem;
use crate::task::Task;
use crate::utils::sigpolicy_from_opts;
Expand Down Expand Up @@ -702,35 +701,6 @@ async fn initialize_ostree_root_from_self(
Ok(aleph)
}

/// Run a command in the host mount namespace
pub(crate) fn run_in_host_mountns(cmd: &str) -> Command {
let mut c = Command::new("/proc/self/exe");
c.args(["exec-in-host-mount-namespace", cmd]);
c
}

#[context("Re-exec in host mountns")]
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
let (cmd, args) = args
.split_first()
.ok_or_else(|| anyhow::anyhow!("Missing command"))?;
tracing::trace!("{cmd:?} {args:?}");
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
nix::sched::setns(pid1mountns.as_fd(), nix::sched::CloneFlags::CLONE_NEWNS).context("setns")?;
rustix::process::chdir("/").context("chdir")?;
// Work around supermin doing chroot() and not pivot_root
// https://github.com/libguestfs/supermin/blob/5230e2c3cd07e82bd6431e871e239f7056bf25ad/init/init.c#L288
if !Utf8Path::new("/usr").try_exists().context("/usr")?
&& Utf8Path::new("/root/usr")
.try_exists()
.context("/root/usr")?
{
tracing::debug!("Using supermin workaround");
rustix::process::chroot("/root").context("chroot")?;
}
Err(Command::new(cmd).args(args).exec()).context("exec")?
}

#[context("Querying skopeo version")]
fn require_skopeo_with_containers_storage() -> Result<()> {
let out = Task::new_cmd("skopeo --version", run_in_host_mountns("skopeo"))
Expand Down
1 change: 1 addition & 0 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
pub mod cli;
pub(crate) mod deploy;
pub(crate) mod generator;
pub(crate) mod hostexec;
pub(crate) mod journal;
mod lsm;
pub(crate) mod metadata;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/podman.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use serde::Deserialize;

use crate::install::run_in_host_mountns;
use crate::hostexec::run_in_host_mountns;
use crate::task::Task;

/// Where we look inside our container to find our own image
Expand Down

0 comments on commit e835d97

Please sign in to comment.