Skip to content

Commit 741e904

Browse files
authored
Merge pull request #730 from cgwalters/install-tmpdir
install: Allocate a global tmpdir
2 parents a557143 + e7be393 commit 741e904

File tree

1 file changed

+29
-25
lines changed

1 file changed

+29
-25
lines changed

lib/src/install.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use camino::Utf8PathBuf;
2626
use cap_std::fs::{Dir, MetadataExt};
2727
use cap_std_ext::cap_std;
2828
use cap_std_ext::cap_std::fs_utf8::DirEntry as DirEntryUtf8;
29+
use cap_std_ext::cap_tempfile::TempDir;
2930
use cap_std_ext::cmdext::CapStdExtCommandExt;
3031
use cap_std_ext::prelude::CapStdExtDirExt;
3132
use chrono::prelude::*;
@@ -322,6 +323,7 @@ pub(crate) struct State {
322323
pub(crate) root_ssh_authorized_keys: Option<String>,
323324
/// The root filesystem of the running container
324325
pub(crate) container_root: Dir,
326+
pub(crate) tempdir: TempDir,
325327
}
326328

327329
impl State {
@@ -342,6 +344,7 @@ impl State {
342344

343345
#[context("Finalizing state")]
344346
pub(crate) fn consume(self) -> Result<()> {
347+
self.tempdir.close()?;
345348
// If we had invoked `setenforce 0`, then let's re-enable it.
346349
if let SELinuxFinalState::Enabled(Some(guard)) = self.selinux_state {
347350
guard.consume()?;
@@ -1001,7 +1004,7 @@ fn ensure_var() -> Result<()> {
10011004
/// via a custom bwrap container today) and work around it by
10021005
/// mounting a writable transient overlayfs.
10031006
#[context("Ensuring writable /etc")]
1004-
fn ensure_writable_etc_containers() -> Result<()> {
1007+
fn ensure_writable_etc_containers(tempdir: &Dir) -> Result<()> {
10051008
let etc_containers = Utf8Path::new("/etc/containers");
10061009
// If there's no /etc/containers, nothing to do
10071010
if !etc_containers.try_exists()? {
@@ -1010,24 +1013,18 @@ fn ensure_writable_etc_containers() -> Result<()> {
10101013
if rustix::fs::access(etc_containers.as_std_path(), rustix::fs::Access::WRITE_OK).is_ok() {
10111014
return Ok(());
10121015
}
1013-
// Create a tempdir for the overlayfs upper; right now this is leaked,
1014-
// but in the case we care about it's into a tmpfs allocated only while
1015-
// we're running (equivalent to PrivateTmp=yes), so it's not
1016-
// really a leak.
1017-
let td = tempfile::tempdir_in("/tmp")?.into_path();
1018-
let td: &Utf8Path = (td.as_path()).try_into()?;
1019-
let upper = &td.join("upper");
1020-
let work = &td.join("work");
1021-
std::fs::create_dir(upper)?;
1022-
std::fs::create_dir(work)?;
1023-
let opts = format!("lowerdir={etc_containers},workdir={work},upperdir={upper}");
1024-
Task::new(
1016+
// Create dirs for the overlayfs upper and work in the install-global tmpdir.
1017+
tempdir.create_dir_all("etc-ovl/upper")?;
1018+
tempdir.create_dir("etc-ovl/work")?;
1019+
let opts = format!("lowerdir={etc_containers},workdir=etc-ovl/work,upperdir=etc-ovl/upper");
1020+
let mut t = Task::new(
10251021
&format!("Mount transient overlayfs for {etc_containers}"),
10261022
"mount",
10271023
)
10281024
.args(["-t", "overlay", "overlay", "-o", opts.as_str()])
1029-
.arg(etc_containers)
1030-
.run()?;
1025+
.arg(etc_containers);
1026+
t.cmd.cwd_dir(tempdir.try_clone()?);
1027+
t.run()?;
10311028
Ok(())
10321029
}
10331030

@@ -1123,11 +1120,12 @@ pub(crate) fn setup_sys_mount(fstype: &str, fspath: &str) -> Result<()> {
11231120

11241121
/// Verify that we can load the manifest of the target image
11251122
#[context("Verifying fetch")]
1126-
async fn verify_target_fetch(imgref: &ostree_container::OstreeImageReference) -> Result<()> {
1127-
let tmpdir = tempfile::tempdir()?;
1128-
let tmprepo = &ostree::Repo::new_for_path(tmpdir.path());
1129-
tmprepo
1130-
.create(ostree::RepoMode::Bare, ostree::gio::Cancellable::NONE)
1123+
async fn verify_target_fetch(
1124+
tmpdir: &Dir,
1125+
imgref: &ostree_container::OstreeImageReference,
1126+
) -> Result<()> {
1127+
let tmpdir = &TempDir::new_in(&tmpdir)?;
1128+
let tmprepo = &ostree::Repo::create_at_dir(tmpdir.as_fd(), ".", ostree::RepoMode::Bare, None)
11311129
.context("Init tmp repo")?;
11321130

11331131
tracing::trace!("Verifying fetch for {imgref}");
@@ -1210,13 +1208,18 @@ async fn prepare_install(
12101208
};
12111209
tracing::debug!("Target image reference: {target_imgref}");
12121210

1213-
if !target_opts.skip_fetch_check {
1214-
verify_target_fetch(&target_imgref).await?;
1215-
}
1216-
1211+
// A bit of basic global state setup
12171212
ensure_var()?;
12181213
setup_tmp_mounts()?;
1219-
ensure_writable_etc_containers()?;
1214+
// Allocate a temporary directory we can use in various places to avoid
1215+
// creating multiple.
1216+
let tempdir = cap_std_ext::cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
1217+
// And continue to init global state
1218+
ensure_writable_etc_containers(&tempdir)?;
1219+
1220+
if !target_opts.skip_fetch_check {
1221+
verify_target_fetch(&tempdir, &target_imgref).await?;
1222+
}
12201223

12211224
// Even though we require running in a container, the mounts we create should be specific
12221225
// to this process, so let's enter a private mountns to avoid leaking them.
@@ -1260,6 +1263,7 @@ async fn prepare_install(
12601263
install_config,
12611264
root_ssh_authorized_keys,
12621265
container_root: rootfs,
1266+
tempdir,
12631267
});
12641268

12651269
Ok(state)

0 commit comments

Comments
 (0)