diff --git a/0001-composepost-Add-and-use-helpers-for-reading-writing-.patch b/0001-composepost-Add-and-use-helpers-for-reading-writing-.patch new file mode 100644 index 0000000..750fb0d --- /dev/null +++ b/0001-composepost-Add-and-use-helpers-for-reading-writing-.patch @@ -0,0 +1,147 @@ +From 5626e776d89a3c3900b504e867aaf83a7efcb269 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Thu, 16 Jun 2022 12:32:37 -0400 +Subject: [PATCH] composepost: Add and use helpers for reading/writing absolute + symlinks + +See https://pagure.io/releng/failed-composes/issue/3660 + +The port to cap-std regressed only the *non-unified* core case +for tmpfiles.d translation. Here cap-std's `read_link()` API correctly +checks for relative paths for the link name, but it *also* bombs +out if the link *target* is absolute, even if we're not going to +follow it. + +I think this is arguably buggy behavior. But, that's a debate +for a future time. + +Now, this bug was masked in our CI because it doesn't occur in +unified core mode where we handle tmpfiles.d translation as part +of package imports. + +Add and use internal helpers for reading (and writing, for tests) +absolute symlinks. +--- + rust/src/capstdext.rs | 55 ++++++++++++++++++++++++++++++++++++++++- + rust/src/composepost.rs | 19 ++++++++++---- + 2 files changed, 68 insertions(+), 6 deletions(-) + +diff --git a/rust/src/capstdext.rs b/rust/src/capstdext.rs +index 99c30967..15b8f51a 100644 +--- a/rust/src/capstdext.rs ++++ b/rust/src/capstdext.rs +@@ -6,9 +6,11 @@ + use cap_std::fs::DirBuilder; + use cap_std_ext::cap_std; + use cap_std_ext::cap_std::fs::Dir; +-use std::ffi::OsStr; ++use cap_std_ext::rustix; ++use std::ffi::{OsStr, OsString}; + use std::io::Result; + use std::os::unix::fs::DirBuilderExt; ++use std::os::unix::prelude::OsStringExt; + use std::path::Path; + + pub(crate) fn dirbuilder_from_mode(m: u32) -> DirBuilder { +@@ -35,3 +37,54 @@ pub(crate) fn open_dir_of( + })?; + Ok((parent, filename)) + } ++ ++pub(crate) fn read_link_contents_impl(dir: &Dir, path: &Path) -> Result { ++ let parent = path ++ .parent() ++ .filter(|v| !v.as_os_str().is_empty()) ++ .unwrap_or_else(|| Path::new(".")); ++ let dir = dir.open_dir(parent)?; ++ let filename = path.file_name().ok_or_else(|| { ++ std::io::Error::new( ++ std::io::ErrorKind::InvalidInput, ++ "the source path does not name a file", ++ ) ++ })?; ++ let l = rustix::fs::readlinkat(&dir, filename, Vec::new())?; ++ Ok(OsString::from_vec(l.into_bytes())) ++} ++ ++// Today cap-std's read_link *also* verifies that the link target doesn't lead outside ++// the filesystem. I think this is arguably incorrect behavior, but for now let's ++// add an API that does this. ++pub(crate) fn read_link_contents(dir: &Dir, path: impl AsRef) -> Result { ++ read_link_contents_impl(dir, path.as_ref()) ++} ++ ++#[cfg(test)] ++pub(crate) fn write_link_contents_impl(dir: &Dir, contents: &OsStr, path: &Path) -> Result<()> { ++ let parent = path ++ .parent() ++ .filter(|v| !v.as_os_str().is_empty()) ++ .unwrap_or_else(|| Path::new(".")); ++ let dir = dir.open_dir(parent)?; ++ let filename = path.file_name().ok_or_else(|| { ++ std::io::Error::new( ++ std::io::ErrorKind::InvalidInput, ++ "the source path does not name a file", ++ ) ++ })?; ++ rustix::fs::symlinkat(contents, &dir, filename).map_err(Into::into) ++} ++ ++// Today cap-std's read_link *also* verifies that the link target doesn't lead outside ++// the filesystem. I think this is arguably incorrect behavior, but for now let's ++// add an API that does this. ++#[cfg(test)] ++pub(crate) fn write_read_link_contents( ++ dir: &Dir, ++ original: impl AsRef, ++ path: impl AsRef, ++) -> Result<()> { ++ write_link_contents_impl(dir, original.as_ref(), path.as_ref()) ++} +diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs +index c486607a..3ddcda49 100644 +--- a/rust/src/composepost.rs ++++ b/rust/src/composepost.rs +@@ -791,11 +791,13 @@ fn convert_path_to_tmpfiles_d_recurse( + file_info.set_file_type(FileType::Directory); + } else if meta.is_symlink() { + file_info.set_file_type(FileType::SymbolicLink); +- let link_target = rootfs.read_link(&full_path).context("Reading symlink")?; +- let target_path = Utf8Path::from_path(&link_target).ok_or_else(|| { +- format_err!("non UTF-8 symlink target '{}'", &link_target.display()) +- })?; +- file_info.set_symlink_target(target_path.as_str()); ++ let link_target = ++ crate::capstdext::read_link_contents(rootfs, full_path.as_std_path()) ++ .context("Reading symlink")?; ++ let link_target = link_target ++ .to_str() ++ .ok_or_else(|| format_err!("non UTF-8 symlink target '{:?}'", link_target))?; ++ file_info.set_symlink_target(link_target); + } else if meta.is_file() { + file_info.set_file_type(FileType::Regular); + } else { +@@ -1344,6 +1346,12 @@ OSTREE_VERSION='33.4' + rootfs + .symlink("../", "var/lib/test/nested/symlink") + .unwrap(); ++ crate::capstdext::write_read_link_contents( ++ &rootfs, ++ "/var/lib/foo", ++ "var/lib/test/absolute-symlink", ++ ) ++ .unwrap(); + + // Also make this a sanity test for our directory size API + let cancellable = gio::Cancellable::new(); +@@ -1364,6 +1372,7 @@ OSTREE_VERSION='33.4' + .map(|s| s.to_owned()) + .collect(); + let expected = &[ ++ "L /var/lib/test/absolute-symlink - - - - /var/lib/foo", + "L /var/lib/test/nested/symlink - - - - ../", + "d /var/lib 0755 test-user test-group - -", + "d /var/lib/nfs 0755 test-user test-group - -", +-- +2.35.1 + diff --git a/rpm-ostree.spec b/rpm-ostree.spec index c54c19a..7a50b30 100644 --- a/rpm-ostree.spec +++ b/rpm-ostree.spec @@ -4,12 +4,14 @@ Summary: Hybrid image/package system Name: rpm-ostree Version: 2022.10 -Release: 2%{?dist} +Release: 3%{?dist} License: LGPLv2+ URL: https://github.com/coreos/rpm-ostree # This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot" # in the upstream git. It also contains vendored Rust sources. Source0: https://github.com/coreos/rpm-ostree/releases/download/v%{version}/rpm-ostree-%{version}.tar.xz +# Backport https://github.com/coreos/rpm-ostree/pull/3771 +Patch0: 0001-composepost-Add-and-use-helpers-for-reading-writing-.patch ExclusiveArch: %{rust_arches} @@ -235,6 +237,9 @@ $PYTHON autofiles.py > files.devel \ %files devel -f files.devel %changelog +* Thu Jun 16 2022 Colin Walters - 2022.10-3 +- Backport https://github.com/coreos/rpm-ostree/pull/3771 + * Tue Jun 14 2022 Colin Walters - 2022.10-2 - https://github.com/coreos/rpm-ostree/releases/tag/v2022.10