From 7473ffd0bd0e30aecfd1af67f3ef7a69af4a4645 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 5 Mar 2025 12:58:07 -0500 Subject: [PATCH] store: Really remove empty /etc/resolv.conf and /etc/hostname The previous change here was a no-op for two reasons: - It's actually usr/etc at this point - We were operating on the wrong rootfs Fixes: https://github.com/containers/bootc/pull/1096/commits/57bd0dc9835669274696998386a547afb6709ff5 Signed-off-by: Colin Walters --- ostree-ext/src/container/store.rs | 32 +++++++++++--------- tests/booted/readonly/011-test-resolvconf.nu | 23 ++++++++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 tests/booted/readonly/011-test-resolvconf.nu diff --git a/ostree-ext/src/container/store.rs b/ostree-ext/src/container/store.rs index 71a9824..2b3f5df 100644 --- a/ostree-ext/src/container/store.rs +++ b/ostree-ext/src/container/store.rs @@ -466,7 +466,7 @@ fn timestamp_of_manifest_or_config( /// Automatically clean up files that may have been injected by container /// builds. xref https://github.com/containers/buildah/issues/4242 fn cleanup_root(root: &Dir) -> Result<()> { - const RUNTIME_INJECTED: &[&str] = &["etc/hostname", "etc/resolv.conf"]; + const RUNTIME_INJECTED: &[&str] = &["usr/etc/hostname", "usr/etc/resolv.conf"]; for ent in RUNTIME_INJECTED { if let Some(meta) = root.symlink_metadata_optional(ent)? { if meta.is_file() && meta.size() == 0 { @@ -1055,6 +1055,8 @@ impl ImageImporter { .with_context(|| format!("Checking out layer {commit}"))?; } + let root_dir = td.open_dir(rootpath)?; + let modifier = ostree::RepoCommitModifier::new(ostree::RepoCommitModifierFlags::CONSUME, None); modifier.set_devino_cache(&devino); @@ -1062,8 +1064,7 @@ impl ImageImporter { // the derived layers include custom policy. Just relabel everything // in this case. if have_derived_layers { - let rootpath = td.open_dir(rootpath)?; - let sepolicy = ostree::SePolicy::new_at(rootpath.as_raw_fd(), cancellable)?; + let sepolicy = ostree::SePolicy::new_at(root_dir.as_raw_fd(), cancellable)?; tracing::debug!("labeling from merged tree"); modifier.set_sepolicy(Some(&sepolicy)); } else if let Some(base) = base_commit.as_ref() { @@ -1074,7 +1075,7 @@ impl ImageImporter { unreachable!() } - cleanup_root(&td)?; + cleanup_root(&root_dir)?; let mt = ostree::MutableTree::new(); repo.write_dfd_to_mtree( @@ -1965,23 +1966,24 @@ mod tests { #[test] fn test_cleanup_root() -> Result<()> { let td = cap_tempfile::TempDir::new(cap_std::ambient_authority())?; - + let usretc = "usr/etc"; cleanup_root(&td).unwrap(); - td.create_dir("etc")?; - td.write("etc/hostname", b"hostname")?; + td.create_dir_all(usretc)?; + let usretc = &td.open_dir(usretc)?; + usretc.write("hostname", b"hostname")?; cleanup_root(&td).unwrap(); - assert!(td.try_exists("etc/hostname")?); - td.write("etc/hostname", b"")?; + assert!(usretc.try_exists("hostname")?); + usretc.write("hostname", b"")?; cleanup_root(&td).unwrap(); - assert!(!td.try_exists("etc/hostname")?); + assert!(!td.try_exists("hostname")?); - td.symlink_contents("../run/systemd/stub-resolv.conf", "etc/resolv.conf")?; + usretc.symlink_contents("../run/systemd/stub-resolv.conf", "resolv.conf")?; cleanup_root(&td).unwrap(); - assert!(td.symlink_metadata("etc/resolv.conf")?.is_symlink()); - td.remove_file("etc/resolv.conf")?; - td.write("etc/resolv.conf", b"")?; + assert!(usretc.symlink_metadata("resolv.conf")?.is_symlink()); + usretc.remove_file("resolv.conf")?; + usretc.write("resolv.conf", b"")?; cleanup_root(&td).unwrap(); - assert!(!td.try_exists("etc/resolv.conf")?); + assert!(!usretc.try_exists("resolv.conf")?); Ok(()) } diff --git a/tests/booted/readonly/011-test-resolvconf.nu b/tests/booted/readonly/011-test-resolvconf.nu new file mode 100644 index 0000000..a5f8fe9 --- /dev/null +++ b/tests/booted/readonly/011-test-resolvconf.nu @@ -0,0 +1,23 @@ +use std assert +use tap.nu + +tap begin "verify there's not an empty /etc/resolv.conf in the image" + +let st = bootc status --json | from json + +let booted_ostree = $st.status.booted.ostree.checksum; + +# ostree ls should probably have --json and a clean way to not error on ENOENT +let resolvconf = ostree ls $booted_ostree /usr/etc | split row (char newline) | find resolv.conf +if ($resolvconf | length) > 0 { + let parts = $resolvconf | first | split row -r '\s+' + let ty = $parts | first | split chars | first + # If resolv.conf exists in the image, currently require it in our + # test suite to be a symlink (which is hopefully to the systemd/stub-resolv.conf) + assert equal $ty 'l' + print "resolv.conf is a symlink" +} else { + print "No resolv.conf found in commit" +} + +tap ok -- 2.48.1