Skip to content

Commit 45b3dc0

Browse files
authored
Merge pull request #38 from cgwalters/install-fixes
Install fixes
2 parents d832d4e + 8da6b5c commit 45b3dc0

File tree

4 files changed

+23
-13
lines changed

4 files changed

+23
-13
lines changed

lib/src/cli.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,21 @@ pub(crate) enum Opt {
113113
pub(crate) async fn ensure_self_unshared_mount_namespace() -> Result<()> {
114114
let uid = cap_std_ext::rustix::process::getuid();
115115
if !uid.is_root() {
116+
tracing::debug!("Not root, assuming no need to unshare");
116117
return Ok(());
117118
}
118119
let recurse_env = "_ostree_unshared";
119120
let ns_pid1 = std::fs::read_link("/proc/1/ns/mnt").context("Reading /proc/1/ns/mnt")?;
120121
let ns_self = std::fs::read_link("/proc/self/ns/mnt").context("Reading /proc/self/ns/mnt")?;
121122
// If we already appear to be in a mount namespace, or we're already pid1, we're done
122123
if ns_pid1 != ns_self {
124+
tracing::debug!("Already in a mount namespace");
123125
return Ok(());
124126
}
125127
if std::env::var_os(recurse_env).is_some() {
126128
let am_pid1 = cap_std_ext::rustix::process::getpid().is_init();
127129
if am_pid1 {
130+
tracing::debug!("We are pid 1");
128131
return Ok(());
129132
} else {
130133
anyhow::bail!("Failed to unshare mount namespace");

lib/src/install.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,12 @@ pub(crate) async fn install(opts: InstallOpts) -> Result<()> {
642642

643643
// Let's ensure we have a tmpfs on /tmp, because we need that to write the SELinux label
644644
// (it won't work on the default overlayfs)
645-
Task::new("Creating tmpfs on /tmp", "mount")
646-
.quiet()
647-
.args(["-t", "tmpfs", "tmpfs", "/tmp"])
648-
.run()?;
645+
if nix::sys::statfs::statfs("/tmp")?.filesystem_type() != nix::sys::statfs::TMPFS_MAGIC {
646+
Task::new("Creating tmpfs on /tmp", "mount")
647+
.quiet()
648+
.args(["-t", "tmpfs", "tmpfs", "/tmp"])
649+
.run()?;
650+
}
649651

650652
// Now, deal with SELinux state.
651653
let srcdata = gather_source_data()?;
@@ -655,6 +657,13 @@ pub(crate) async fn install(opts: InstallOpts) -> Result<()> {
655657
let host_selinux = crate::lsm::selinux_enabled()?;
656658
tracing::debug!("Target has SELinux, host={host_selinux}");
657659
if host_selinux {
660+
// /sys/fs/selinuxfs is not normally mounted, so we do that now.
661+
// Because SELinux enablement status is cached process-wide and was very likely
662+
// already queried by something else (e.g. glib's constructor), we would also need
663+
// to re-exec. But, selinux_ensure_install does that unconditionally right now too,
664+
// so let's just fall through to that.
665+
crate::lsm::container_setup_selinux()?;
666+
// This will re-execute the current process (once).
658667
crate::lsm::selinux_ensure_install()?;
659668
} else if opts.disable_selinux {
660669
override_disable_selinux = true;
@@ -668,13 +677,6 @@ pub(crate) async fn install(opts: InstallOpts) -> Result<()> {
668677
tracing::debug!("Target does not enable SELinux");
669678
}
670679

671-
// Because SELinux enablement status is cached process-wide and was very likely
672-
// already queried by something else (e.g. glib's constructor), we need to mount
673-
// selinuxfs now if needed, then re-exec *again*.
674-
if srcdata.selinux && !override_disable_selinux {
675-
crate::lsm::container_setup_selinux()?;
676-
}
677-
678680
// Create our global (read-only) state which gets wrapped in an Arc
679681
// so we can pass it to worker threads too. Right now this just
680682
// combines our command line options along with some bind mounts from the host.

lib/src/lsm.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub(crate) fn selinux_ensure_install() -> Result<()> {
2929
if p.exists() {
3030
tracing::debug!("Removing temporary file");
3131
std::fs::remove_file(p).context("Removing {p:?}")?;
32+
} else {
33+
tracing::debug!("Assuming we now have a privileged (e.g. install_t) label");
3234
}
3335
return Ok(());
3436
}
@@ -50,6 +52,7 @@ pub(crate) fn selinux_ensure_install() -> Result<()> {
5052
let mut cmd = Command::new(&tmpf);
5153
cmd.env(guardenv, tmpf);
5254
cmd.args(std::env::args_os().skip(1));
55+
tracing::debug!("Re-executing");
5356
Err(anyhow::Error::msg(cmd.exec()).context("execve"))
5457
}
5558

@@ -60,14 +63,14 @@ pub(crate) fn container_setup_selinux() -> Result<()> {
6063
let path = Utf8Path::new(SELINUXFS);
6164
if !path.join("enforce").exists() {
6265
if !path.exists() {
66+
tracing::debug!("Creating {path}");
6367
std::fs::create_dir(path)?;
6468
}
6569
Task::new("Mounting selinuxfs", "mount")
6670
.args(["selinuxfs", "-t", "selinuxfs", path.as_str()])
6771
.run()?;
6872
}
69-
70-
selinux_ensure_install()
73+
Ok(())
7174
}
7275

7376
fn selinux_label_for_path(target: &str) -> Result<String> {

lib/src/reexec.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use fn_error_context::context;
88
#[context("Reexec self")]
99
pub(crate) fn reexec_with_guardenv(k: &str, prefix_args: &[&str]) -> Result<()> {
1010
if std::env::var_os(k).is_some() {
11+
tracing::trace!("Skipping re-exec due to env var {k}");
1112
return Ok(());
1213
}
1314
let self_exe = std::fs::read_link("/proc/self/exe")?;
@@ -22,5 +23,6 @@ pub(crate) fn reexec_with_guardenv(k: &str, prefix_args: &[&str]) -> Result<()>
2223
};
2324
cmd.env(k, "1");
2425
cmd.args(std::env::args_os().skip(1));
26+
tracing::debug!("Re-executing current process for {k}");
2527
Err(cmd.exec().into())
2628
}

0 commit comments

Comments
 (0)