import CS rpm-ostree-2024.7-3.el9_5
This commit is contained in:
parent
ebe83f9794
commit
7e3b91c77a
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/rpm-ostree-2024.3.tar.xz
|
SOURCES/rpm-ostree-2024.7.tar.xz
|
||||||
|
@ -1 +1 @@
|
|||||||
dc6e0ea9f33f162b5ca2d1ea1cb79ec7f9f7d71c SOURCES/rpm-ostree-2024.3.tar.xz
|
d9cceab814a10d116e41911a00ca5d5134715da1 SOURCES/rpm-ostree-2024.7.tar.xz
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
From d02993e30078db2a04820065ccbf22bd56d0d064 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jonathan Lebon <jonathan@jlebon.com>
|
|
||||||
Date: Thu, 22 Feb 2024 14:44:50 -0500
|
|
||||||
Subject: [PATCH] cliwrap/rpm: mark `--eval`/`-E` as safe
|
|
||||||
|
|
||||||
This is sometimes used in scripts to query aspects of the host system.
|
|
||||||
E.g. this is used by Fedora's pkg-config:
|
|
||||||
|
|
||||||
https://src.fedoraproject.org/rpms/pkgconf/blob/95c0bbee/f/pkg-config.in#_6
|
|
||||||
|
|
||||||
This in turn gets hit by kdump which runs dracut which has modules that
|
|
||||||
runs `pkgconf` to query some directory paths.
|
|
||||||
---
|
|
||||||
rust/src/cliwrap/rpm.rs | 19 +++++++++++++++++++
|
|
||||||
1 file changed, 19 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/rust/src/cliwrap/rpm.rs b/rust/src/cliwrap/rpm.rs
|
|
||||||
index c6ed5901..3332f76c 100644
|
|
||||||
--- a/rust/src/cliwrap/rpm.rs
|
|
||||||
+++ b/rust/src/cliwrap/rpm.rs
|
|
||||||
@@ -19,6 +19,12 @@ fn new_rpm_app() -> Command {
|
|
||||||
.long("version")
|
|
||||||
.action(clap::ArgAction::Version),
|
|
||||||
)
|
|
||||||
+ .arg(
|
|
||||||
+ Arg::new("eval")
|
|
||||||
+ .long("eval")
|
|
||||||
+ .short('E')
|
|
||||||
+ .action(clap::ArgAction::Set),
|
|
||||||
+ )
|
|
||||||
.arg(
|
|
||||||
Arg::new("package")
|
|
||||||
.help("package")
|
|
||||||
@@ -130,6 +136,19 @@ mod tests {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
+ #[test]
|
|
||||||
+ fn test_eval() -> Result<()> {
|
|
||||||
+ assert_eq!(
|
|
||||||
+ disposition(SystemHostType::OstreeHost, &["-E", "%{_target_cpu}"])?,
|
|
||||||
+ RunDisposition::Ok
|
|
||||||
+ );
|
|
||||||
+ assert_eq!(
|
|
||||||
+ disposition(SystemHostType::OstreeHost, &["--eval=%{_target_cpu}}"])?,
|
|
||||||
+ RunDisposition::Ok
|
|
||||||
+ );
|
|
||||||
+ Ok(())
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
#[test]
|
|
||||||
fn test_query_file() -> Result<()> {
|
|
||||||
assert_eq!(
|
|
||||||
--
|
|
||||||
2.43.2
|
|
||||||
|
|
33
SOURCES/0001-core-Fix-Coverity-WRAPPER_ESCAPE.patch
Normal file
33
SOURCES/0001-core-Fix-Coverity-WRAPPER_ESCAPE.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
From 96ddae1acba59cf5249dcfff1157e44b5ed69650 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Colin Walters <walters@verbum.org>
|
||||||
|
Date: Thu, 15 Aug 2024 11:41:43 -0400
|
||||||
|
Subject: [PATCH 1/1] core: Fix Coverity WRAPPER_ESCAPE
|
||||||
|
|
||||||
|
This should fix:
|
||||||
|
|
||||||
|
```
|
||||||
|
32. rpm-ostree-2024.7/src/libpriv/rpmostree-core.cxx:1786:15: use_after_free: Using internal representation of destroyed object temporary of type "std::string".
|
||||||
|
```
|
||||||
|
|
||||||
|
Signed-off-by: Colin Walters <walters@verbum.org>
|
||||||
|
---
|
||||||
|
src/libpriv/rpmostree-core.cxx | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx
|
||||||
|
index a2de7262..615e2636 100644
|
||||||
|
--- a/src/libpriv/rpmostree-core.cxx
|
||||||
|
+++ b/src/libpriv/rpmostree-core.cxx
|
||||||
|
@@ -1782,7 +1782,8 @@ rpmostree_context_prepare (RpmOstreeContext *self, gboolean enable_filelists,
|
||||||
|
auto pkg = "";
|
||||||
|
for (auto &pkg_str : packages)
|
||||||
|
{
|
||||||
|
- pkg = std::string (pkg_str).c_str ();
|
||||||
|
+ auto pkg_buf = std::string (pkg_str);
|
||||||
|
+ pkg = pkg_buf.c_str ();
|
||||||
|
char *query = strchr ((char *)pkg, '/');
|
||||||
|
if (query)
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
@ -1,83 +0,0 @@
|
|||||||
From ef2638c1ffd77bc6fd9a80a92c965b06a8f284df Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jonathan Lebon <jonathan@jlebon.com>
|
|
||||||
Date: Tue, 19 Mar 2024 15:20:43 -0400
|
|
||||||
Subject: [PATCH 1/3] passwd: create `/etc/[g]shadow` with mode 0
|
|
||||||
|
|
||||||
Because of how our composes work, we need to manually inject
|
|
||||||
passwd-related things before installing packages. A somewhat recent
|
|
||||||
regression in that area made it so that the `/etc/shadow` and
|
|
||||||
`/etc/gshadow` files were created with default permissions (0644), which
|
|
||||||
meant they were world readable.
|
|
||||||
|
|
||||||
Fix this by explicitly setting their modes to 0. Ideally, we would rely
|
|
||||||
on the canonical permissions set in the `setup` package here, but it's
|
|
||||||
tricky to fix that without reworking how we install `setup` and handle
|
|
||||||
`passwd` treefile options.
|
|
||||||
|
|
||||||
Fixes fdb879c8 ("passwd: sync `etc/{,g}shadow` according to
|
|
||||||
`etc/{passwd,group}`").
|
|
||||||
|
|
||||||
Fixes #4401
|
|
||||||
---
|
|
||||||
rust/src/passwd.rs | 14 ++++++++++++++
|
|
||||||
tests/compose/libbasic-test.sh | 5 +++++
|
|
||||||
2 files changed, 19 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/rust/src/passwd.rs b/rust/src/passwd.rs
|
|
||||||
index 821497d8..a64f6468 100644
|
|
||||||
--- a/rust/src/passwd.rs
|
|
||||||
+++ b/rust/src/passwd.rs
|
|
||||||
@@ -418,6 +418,12 @@ fn write_data_from_treefile(
|
|
||||||
let db = rootfs.open(target_passwd_path).map(BufReader::new)?;
|
|
||||||
let shadow_name = target.shadow_file();
|
|
||||||
let target_shadow_path = format!("{}{}", dest_path, shadow_name);
|
|
||||||
+ // Ideally these permissions come from `setup`, which is the package
|
|
||||||
+ // that owns these files:
|
|
||||||
+ // https://src.fedoraproject.org/rpms/setup/blob/c6f58b338bd3/f/setup.spec#_96
|
|
||||||
+ // But at this point of the compose, the rootfs is completely empty; we
|
|
||||||
+ // haven't started unpacking things yet. So we need to hardcode it here.
|
|
||||||
+ let shadow_perms = cap_std::fs::Permissions::from_mode(0);
|
|
||||||
|
|
||||||
match target {
|
|
||||||
PasswdKind::User => {
|
|
||||||
@@ -427,6 +433,10 @@ fn write_data_from_treefile(
|
|
||||||
for user in entries {
|
|
||||||
writeln!(target_shadow, "{}:*::0:99999:7:::", user.name)?;
|
|
||||||
}
|
|
||||||
+ target_shadow
|
|
||||||
+ .get_mut()
|
|
||||||
+ .as_file_mut()
|
|
||||||
+ .set_permissions(shadow_perms)?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.with_context(|| format!("Writing {target_shadow_path}"))?;
|
|
||||||
@@ -438,6 +448,10 @@ fn write_data_from_treefile(
|
|
||||||
for group in entries {
|
|
||||||
writeln!(target_shadow, "{}:::", group.name)?;
|
|
||||||
}
|
|
||||||
+ target_shadow
|
|
||||||
+ .get_mut()
|
|
||||||
+ .as_file_mut()
|
|
||||||
+ .set_permissions(shadow_perms)?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.with_context(|| format!("Writing {target_shadow_path}"))?;
|
|
||||||
diff --git a/tests/compose/libbasic-test.sh b/tests/compose/libbasic-test.sh
|
|
||||||
index 78ad72b1..df790e89 100644
|
|
||||||
--- a/tests/compose/libbasic-test.sh
|
|
||||||
+++ b/tests/compose/libbasic-test.sh
|
|
||||||
@@ -22,6 +22,11 @@ validate_passwd group
|
|
||||||
ostree --repo=${repo} ls ${treeref} /usr/etc/passwd > passwd.txt
|
|
||||||
assert_file_has_content_literal passwd.txt '00644 '
|
|
||||||
|
|
||||||
+ostree --repo=${repo} ls ${treeref} /usr/etc/shadow > shadow.txt
|
|
||||||
+assert_file_has_content_literal shadow.txt '00000 '
|
|
||||||
+ostree --repo=${repo} ls ${treeref} /usr/etc/gshadow > gshadow.txt
|
|
||||||
+assert_file_has_content_literal gshadow.txt '00000 '
|
|
||||||
+
|
|
||||||
ostree --repo=${repo} cat ${treeref} /usr/etc/default/useradd > useradd.txt
|
|
||||||
assert_file_has_content_literal useradd.txt HOME=/var/home
|
|
||||||
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
332
SOURCES/0001-treefile-Add-ignore-devices.patch
Normal file
332
SOURCES/0001-treefile-Add-ignore-devices.patch
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
From aeb048ce390fcd82e568ba25c0047099b8892979 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Colin Walters <walters@verbum.org>
|
||||||
|
Date: Tue, 1 Oct 2024 17:56:38 -0400
|
||||||
|
Subject: [PATCH 1/1] treefile: Add ignore-devices
|
||||||
|
|
||||||
|
We hit another case where people are pulling a container image
|
||||||
|
with devices in `/dev` in the tar stream; they're then trying
|
||||||
|
to commit this to an ostree.
|
||||||
|
|
||||||
|
There's much better ways to fix this:
|
||||||
|
|
||||||
|
- Change the image to stop including devices as there's no reason
|
||||||
|
to do so
|
||||||
|
- Switch to logically bound images instead of physically bound
|
||||||
|
- Use the composefs backend for c/storage
|
||||||
|
|
||||||
|
Eventually I may look at "quoting" generally in ostree, but
|
||||||
|
it's fairly invasive: https://github.com/ostreedev/ostree/issues/2568
|
||||||
|
|
||||||
|
In practice today, simply ignoring the files will happen to work
|
||||||
|
for "podman run" of such images; podman will just use overlayfs
|
||||||
|
to stitch together the `diff` directories, and doesn't try to do
|
||||||
|
any validation of their contents today.
|
||||||
|
(Queue the composefs integration, which *would* do that but would
|
||||||
|
also fix this anwyays)
|
||||||
|
|
||||||
|
Signed-off-by: Colin Walters <walters@verbum.org>
|
||||||
|
---
|
||||||
|
docs/treefile.md | 4 ++
|
||||||
|
rpmostree-cxxrs.cxx | 11 ++--
|
||||||
|
rpmostree-cxxrs.h | 5 +-
|
||||||
|
rust/src/composepost.rs | 74 +++++++++++++++++++--------
|
||||||
|
rust/src/lib.rs | 2 +-
|
||||||
|
rust/src/treefile.rs | 7 +++
|
||||||
|
src/libpriv/rpmostree-postprocess.cxx | 2 +-
|
||||||
|
tests/compose/test-installroot.sh | 8 +++
|
||||||
|
8 files changed, 84 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/treefile.md b/docs/treefile.md
|
||||||
|
index 9839589e..49e193d1 100644
|
||||||
|
--- a/docs/treefile.md
|
||||||
|
+++ b/docs/treefile.md
|
||||||
|
@@ -36,6 +36,10 @@ It supports the following parameters:
|
||||||
|
* `selinux`: boolean, optional: Defaults to `true`. If `false`, then
|
||||||
|
no SELinux labeling will be performed on the server side.
|
||||||
|
|
||||||
|
+ * `ignore-devices`: boolean, optional: Defaults to `true`. If `true`, then
|
||||||
|
+ all character and block device files found in the target root (except overlayfs
|
||||||
|
+ whiteouts, which are automatically "quoted") will be ignored.
|
||||||
|
+
|
||||||
|
* `ima`: boolean, optional: Defaults to `false`. Propagate any
|
||||||
|
IMA signatures in input RPMs into the final OSTree commit.
|
||||||
|
|
||||||
|
diff --git a/rpmostree-cxxrs.cxx b/rpmostree-cxxrs.cxx
|
||||||
|
index 649d1b7b..2a4cb12c 100644
|
||||||
|
--- a/rpmostree-cxxrs.cxx
|
||||||
|
+++ b/rpmostree-cxxrs.cxx
|
||||||
|
@@ -192,6 +192,8 @@ public:
|
||||||
|
Slice () noexcept;
|
||||||
|
Slice (T *, std::size_t count) noexcept;
|
||||||
|
|
||||||
|
+ template <typename C> explicit Slice (C &c) : Slice (c.data (), c.size ()) {}
|
||||||
|
+
|
||||||
|
Slice &operator= (const Slice<T> &) &noexcept = default;
|
||||||
|
Slice &operator= (Slice<T> &&) &noexcept = default;
|
||||||
|
|
||||||
|
@@ -2206,8 +2208,8 @@ extern "C"
|
||||||
|
::std::int32_t rootfs_dfd, ::rpmostreecxx::Treefile &treefile, ::rust::Str next_version,
|
||||||
|
bool unified_core) noexcept;
|
||||||
|
|
||||||
|
- ::rust::repr::PtrLen
|
||||||
|
- rpmostreecxx$cxxbridge1$compose_postprocess_final_pre (::std::int32_t rootfs_dfd) noexcept;
|
||||||
|
+ ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$compose_postprocess_final_pre (
|
||||||
|
+ ::std::int32_t rootfs_dfd, ::rpmostreecxx::Treefile const &treefile) noexcept;
|
||||||
|
|
||||||
|
::rust::repr::PtrLen rpmostreecxx$cxxbridge1$compose_postprocess_final (
|
||||||
|
::std::int32_t rootfs_dfd, ::rpmostreecxx::Treefile const &treefile) noexcept;
|
||||||
|
@@ -4011,9 +4013,10 @@ compose_postprocess (::std::int32_t rootfs_dfd, ::rpmostreecxx::Treefile &treefi
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-compose_postprocess_final_pre (::std::int32_t rootfs_dfd)
|
||||||
|
+compose_postprocess_final_pre (::std::int32_t rootfs_dfd, ::rpmostreecxx::Treefile const &treefile)
|
||||||
|
{
|
||||||
|
- ::rust::repr::PtrLen error$ = rpmostreecxx$cxxbridge1$compose_postprocess_final_pre (rootfs_dfd);
|
||||||
|
+ ::rust::repr::PtrLen error$
|
||||||
|
+ = rpmostreecxx$cxxbridge1$compose_postprocess_final_pre (rootfs_dfd, treefile);
|
||||||
|
if (error$.ptr)
|
||||||
|
{
|
||||||
|
throw ::rust::impl< ::rust::Error>::error (error$);
|
||||||
|
diff --git a/rpmostree-cxxrs.h b/rpmostree-cxxrs.h
|
||||||
|
index d38fd1db..9d62380e 100644
|
||||||
|
--- a/rpmostree-cxxrs.h
|
||||||
|
+++ b/rpmostree-cxxrs.h
|
||||||
|
@@ -191,6 +191,8 @@ public:
|
||||||
|
Slice () noexcept;
|
||||||
|
Slice (T *, std::size_t count) noexcept;
|
||||||
|
|
||||||
|
+ template <typename C> explicit Slice (C &c) : Slice (c.data (), c.size ()) {}
|
||||||
|
+
|
||||||
|
Slice &operator= (const Slice<T> &) &noexcept = default;
|
||||||
|
Slice &operator= (Slice<T> &&) &noexcept = default;
|
||||||
|
|
||||||
|
@@ -1867,7 +1869,8 @@ void composepost_nsswitch_altfiles (::std::int32_t rootfs_dfd);
|
||||||
|
void compose_postprocess (::std::int32_t rootfs_dfd, ::rpmostreecxx::Treefile &treefile,
|
||||||
|
::rust::Str next_version, bool unified_core);
|
||||||
|
|
||||||
|
-void compose_postprocess_final_pre (::std::int32_t rootfs_dfd);
|
||||||
|
+void compose_postprocess_final_pre (::std::int32_t rootfs_dfd,
|
||||||
|
+ ::rpmostreecxx::Treefile const &treefile);
|
||||||
|
|
||||||
|
void compose_postprocess_final (::std::int32_t rootfs_dfd,
|
||||||
|
::rpmostreecxx::Treefile const &treefile);
|
||||||
|
diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs
|
||||||
|
index 1a5ae869..8049d502 100644
|
||||||
|
--- a/rust/src/composepost.rs
|
||||||
|
+++ b/rust/src/composepost.rs
|
||||||
|
@@ -295,40 +295,69 @@ fn is_overlay_whiteout(meta: &cap_std::fs::Metadata) -> bool {
|
||||||
|
(meta.mode() & libc::S_IFMT) == libc::S_IFCHR && meta.rdev() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
-/// Auto-synthesize embedded overlayfs whiteouts; for more information
|
||||||
|
-/// see https://github.com/ostreedev/ostree/pull/2722/commits/0085494e350c72599fc5c0e00422885d80b3c660
|
||||||
|
-#[context("Postprocessing embedded overlayfs")]
|
||||||
|
-fn postprocess_embedded_ovl_whiteouts(root: &Dir) -> Result<()> {
|
||||||
|
+/// Automatically "quote" embeded overlayfs whiteouts as regular files, and
|
||||||
|
+/// if configured error out on devices or ignore them.
|
||||||
|
+/// For more on overlayfs, see https://github.com/ostreedev/ostree/pull/2722/commits/0085494e350c72599fc5c0e00422885d80b3c660
|
||||||
|
+#[context("Postprocessing devices")]
|
||||||
|
+fn postprocess_devices(root: &Dir, treefile: &Treefile) -> Result<()> {
|
||||||
|
const OSTREE_WHITEOUT_PREFIX: &str = ".ostree-wh.";
|
||||||
|
- fn recurse(root: &Dir, path: &Utf8Path) -> Result<u32> {
|
||||||
|
- let mut n = 0;
|
||||||
|
+ let mut n_overlay = 0u64;
|
||||||
|
+ let mut n_devices = 0u64;
|
||||||
|
+ fn recurse(
|
||||||
|
+ root: &Dir,
|
||||||
|
+ path: &Utf8Path,
|
||||||
|
+ ignore_devices: bool,
|
||||||
|
+ n_overlay: &mut u64,
|
||||||
|
+ n_devices: &mut u64,
|
||||||
|
+ ) -> Result<()> {
|
||||||
|
for entry in root.read_dir(path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let meta = entry.metadata()?;
|
||||||
|
let name = PathBuf::from(entry.file_name());
|
||||||
|
let name: Utf8PathBuf = name.try_into()?;
|
||||||
|
if meta.is_dir() {
|
||||||
|
- n += recurse(root, &path.join(name))?;
|
||||||
|
+ recurse(root, &path.join(name), ignore_devices, n_overlay, n_devices)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if !is_overlay_whiteout(&meta) {
|
||||||
|
+ let is_device = matches!(meta.mode() & libc::S_IFMT, libc::S_IFCHR | libc::S_IFBLK);
|
||||||
|
+ if !is_device {
|
||||||
|
continue;
|
||||||
|
- };
|
||||||
|
+ }
|
||||||
|
let srcpath = path.join(&name);
|
||||||
|
- let targetname = format!("{OSTREE_WHITEOUT_PREFIX}{name}");
|
||||||
|
- let destpath = path.join(&targetname);
|
||||||
|
- root.remove_file(srcpath)?;
|
||||||
|
- root.atomic_write_with_perms(destpath, "", meta.permissions())?;
|
||||||
|
- n += 1;
|
||||||
|
+ if is_overlay_whiteout(&meta) {
|
||||||
|
+ let targetname = format!("{OSTREE_WHITEOUT_PREFIX}{name}");
|
||||||
|
+ let destpath = path.join(&targetname);
|
||||||
|
+ root.remove_file(srcpath)?;
|
||||||
|
+ root.atomic_write_with_perms(destpath, "", meta.permissions())?;
|
||||||
|
+ *n_overlay += 1;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if ignore_devices {
|
||||||
|
+ root.remove_file(srcpath)?;
|
||||||
|
+ *n_devices += 1;
|
||||||
|
+ } else {
|
||||||
|
+ anyhow::bail!("Unsupported device file: {srcpath}")
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- Ok(n)
|
||||||
|
+ Ok(())
|
||||||
|
}
|
||||||
|
- let n = recurse(root, ".".into())?;
|
||||||
|
- if n > 0 {
|
||||||
|
- println!("Processed {n} embedded whiteouts");
|
||||||
|
+ recurse(
|
||||||
|
+ root,
|
||||||
|
+ ".".into(),
|
||||||
|
+ treefile.get_ignore_devices(),
|
||||||
|
+ &mut n_overlay,
|
||||||
|
+ &mut n_devices,
|
||||||
|
+ )?;
|
||||||
|
+ if n_overlay > 0 {
|
||||||
|
+ println!("Processed {n_overlay} embedded whiteouts");
|
||||||
|
} else {
|
||||||
|
println!("No embedded whiteouts found");
|
||||||
|
}
|
||||||
|
+ if n_devices > 0 {
|
||||||
|
+ println!("Ignored {n_devices} device files");
|
||||||
|
+ } else {
|
||||||
|
+ println!("No device files found");
|
||||||
|
+ }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -420,7 +449,7 @@ pub(crate) fn postprocess_cleanup_rpmdb(rootfs_dfd: i32) -> CxxResult<()> {
|
||||||
|
/// it as the bits of that function that we've chosen to implement in Rust.
|
||||||
|
/// It takes care of all things that are really required to use rpm-ostree
|
||||||
|
/// on the target host.
|
||||||
|
-pub fn compose_postprocess_final_pre(rootfs_dfd: i32) -> CxxResult<()> {
|
||||||
|
+pub fn compose_postprocess_final_pre(rootfs_dfd: i32, treefile: &Treefile) -> CxxResult<()> {
|
||||||
|
let rootfs_dfd = unsafe { &crate::ffiutil::ffi_dirfd(rootfs_dfd)? };
|
||||||
|
// These tasks can safely run in parallel, so just for fun we do so via rayon.
|
||||||
|
let tasks = [
|
||||||
|
@@ -430,7 +459,7 @@ pub fn compose_postprocess_final_pre(rootfs_dfd: i32) -> CxxResult<()> {
|
||||||
|
];
|
||||||
|
tasks.par_iter().try_for_each(|f| f(rootfs_dfd))?;
|
||||||
|
// This task recursively traverses the filesystem and hence should be serial.
|
||||||
|
- postprocess_embedded_ovl_whiteouts(rootfs_dfd)?;
|
||||||
|
+ postprocess_devices(rootfs_dfd, treefile)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1533,11 +1562,12 @@ OSTREE_VERSION='33.4'
|
||||||
|
// We don't actually test creating whiteout devices here as that
|
||||||
|
// may not work.
|
||||||
|
let td = cap_tempfile::tempdir(cap_std::ambient_authority())?;
|
||||||
|
+ let tf = crate::treefile::tests::new_test_tf_basic("")?;
|
||||||
|
// Verify no-op case
|
||||||
|
- postprocess_embedded_ovl_whiteouts(&td).unwrap();
|
||||||
|
+ postprocess_devices(&td, &tf).unwrap();
|
||||||
|
td.create("foo")?;
|
||||||
|
td.symlink("foo", "bar")?;
|
||||||
|
- postprocess_embedded_ovl_whiteouts(&td).unwrap();
|
||||||
|
+ postprocess_devices(&td, &tf).unwrap();
|
||||||
|
assert!(td.try_exists("foo")?);
|
||||||
|
assert!(td.try_exists("bar")?);
|
||||||
|
|
||||||
|
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
|
||||||
|
index 56d8b57f..5356dc8c 100644
|
||||||
|
--- a/rust/src/lib.rs
|
||||||
|
+++ b/rust/src/lib.rs
|
||||||
|
@@ -299,7 +299,7 @@ pub mod ffi {
|
||||||
|
next_version: &str,
|
||||||
|
unified_core: bool,
|
||||||
|
) -> Result<()>;
|
||||||
|
- fn compose_postprocess_final_pre(rootfs_dfd: i32) -> Result<()>;
|
||||||
|
+ fn compose_postprocess_final_pre(rootfs_dfd: i32, treefile: &Treefile) -> Result<()>;
|
||||||
|
fn compose_postprocess_final(rootfs_dfd: i32, treefile: &Treefile) -> Result<()>;
|
||||||
|
fn convert_var_to_tmpfiles_d(rootfs_dfd: i32, cancellable: &GCancellable) -> Result<()>;
|
||||||
|
fn rootfs_prepare_links(
|
||||||
|
diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs
|
||||||
|
index da6c0ca7..51dfff6d 100644
|
||||||
|
--- a/rust/src/treefile.rs
|
||||||
|
+++ b/rust/src/treefile.rs
|
||||||
|
@@ -394,6 +394,7 @@ fn treefile_merge(dest: &mut TreeComposeConfig, src: &mut TreeComposeConfig) {
|
||||||
|
rojig,
|
||||||
|
selinux,
|
||||||
|
selinux_label_version,
|
||||||
|
+ ignore_devices,
|
||||||
|
ima,
|
||||||
|
gpg_key,
|
||||||
|
include,
|
||||||
|
@@ -1245,6 +1246,10 @@ impl Treefile {
|
||||||
|
self.parsed.base.selinux.unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
+ pub(crate) fn get_ignore_devices(&self) -> bool {
|
||||||
|
+ self.parsed.base.ignore_devices.unwrap_or(true)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
pub(crate) fn get_selinux_label_version(&self) -> u32 {
|
||||||
|
self.parsed.base.selinux_label_version.unwrap_or_default()
|
||||||
|
}
|
||||||
|
@@ -2414,6 +2419,8 @@ pub(crate) struct BaseComposeConfigFields {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub(crate) selinux: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
+ pub(crate) ignore_devices: Option<bool>,
|
||||||
|
+ #[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub(crate) selinux_label_version: Option<u32>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub(crate) ima: Option<bool>,
|
||||||
|
diff --git a/src/libpriv/rpmostree-postprocess.cxx b/src/libpriv/rpmostree-postprocess.cxx
|
||||||
|
index 311de70f..c086bcdd 100644
|
||||||
|
--- a/src/libpriv/rpmostree-postprocess.cxx
|
||||||
|
+++ b/src/libpriv/rpmostree-postprocess.cxx
|
||||||
|
@@ -381,7 +381,7 @@ postprocess_final (int rootfs_dfd, rpmostreecxx::Treefile &treefile, gboolean un
|
||||||
|
|
||||||
|
auto selinux = treefile.get_selinux ();
|
||||||
|
|
||||||
|
- ROSCXX_TRY (compose_postprocess_final_pre (rootfs_dfd), error);
|
||||||
|
+ ROSCXX_TRY (compose_postprocess_final_pre (rootfs_dfd, treefile), error);
|
||||||
|
|
||||||
|
if (selinux)
|
||||||
|
{
|
||||||
|
diff --git a/tests/compose/test-installroot.sh b/tests/compose/test-installroot.sh
|
||||||
|
index 3e40f679..90a11ee3 100755
|
||||||
|
--- a/tests/compose/test-installroot.sh
|
||||||
|
+++ b/tests/compose/test-installroot.sh
|
||||||
|
@@ -7,6 +7,8 @@ dn=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
|
||||||
|
# This is used to test postprocessing with treefile vs not
|
||||||
|
treefile_set "boot-location" '"new"'
|
||||||
|
+# On by default now:
|
||||||
|
+# treefile_set "ignore-devices" 'True'
|
||||||
|
|
||||||
|
# This test is a bit of a degenerative case of the supermin abstration. We need
|
||||||
|
# to be able to interact with the compose output directly, feed it back to
|
||||||
|
@@ -56,6 +58,7 @@ testdate=$(date)
|
||||||
|
runasroot sh -xec "
|
||||||
|
# https://github.com/ostreedev/ostree/pull/2717/commits/e234b630f85b97e48ecf45d5aaba9b1aa64e6b54
|
||||||
|
mknod -m 000 ${instroot}-directcommit/usr/share/foowhiteout c 0 0
|
||||||
|
+mknod -m 000 ${instroot}-directcommit/usr/share/devzero c 1 5
|
||||||
|
echo \"${testdate}\" > ${instroot}-directcommit/usr/share/rpm-ostree-composetest-split.txt
|
||||||
|
! test -f ${instroot}-directcommit/${integrationconf}
|
||||||
|
rpm-ostree compose commit --repo=${repo} ${treefile} ${instroot}-directcommit
|
||||||
|
@@ -69,6 +72,11 @@ ostree --repo=${repo} ls ${treeref} /usr/share
|
||||||
|
ostree --repo=${repo} ls ${treeref} /usr/share/.ostree-wh.foowhiteout >out.txt
|
||||||
|
grep -Ee '^-00000' out.txt
|
||||||
|
|
||||||
|
+# And the devzero should have been ignored
|
||||||
|
+if ostree --repo=${repo} ls ${treeref} /usr/share/devzero; then
|
||||||
|
+ echo \"found devzero\" 1>&2; exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
ostree --repo=${repo} cat ${treeref} /usr/share/rpm-ostree-composetest-split.txt >out.txt
|
||||||
|
grep \"${testdate}\" out.txt
|
||||||
|
ostree --repo=${repo} cat ${treeref} /${integrationconf}
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
From 715298d909551b7d6b42ee6f9c38675f22034dde Mon Sep 17 00:00:00 2001
|
|
||||||
From: jbtrystram <jbtrystram@redhat.com>
|
|
||||||
Date: Thu, 21 Mar 2024 17:27:21 +0100
|
|
||||||
Subject: [PATCH 2/3] unit: chmod /etc/[g]shadow[-] to 0000
|
|
||||||
|
|
||||||
fdb879c introduced a regression where /etc/[g]shadow[-] files where
|
|
||||||
created with default permissions: 0644
|
|
||||||
|
|
||||||
This unit chmods /etc/shadow, /etc/gshadow and backup copies to 0000
|
|
||||||
before interactive login is allowed on a system.
|
|
||||||
|
|
||||||
This will fix the systems that were deployed with the above issue.
|
|
||||||
|
|
||||||
We keep the stamp in /etc to account for the case where a deployment
|
|
||||||
with this unit is rolled back. If we used /var, the stamp would have
|
|
||||||
stayed but the fix would not be re-applied on the next update.
|
|
||||||
---
|
|
||||||
Makefile-daemon.am | 1 +
|
|
||||||
packaging/rpm-ostree.spec.in | 5 +++++
|
|
||||||
src/daemon/rpm-ostree-fix-shadow-mode.service | 19 +++++++++++++++++++
|
|
||||||
3 files changed, 25 insertions(+)
|
|
||||||
create mode 100644 src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
|
|
||||||
diff --git a/Makefile-daemon.am b/Makefile-daemon.am
|
|
||||||
index 4233d90d..f96f49a9 100644
|
|
||||||
--- a/Makefile-daemon.am
|
|
||||||
+++ b/Makefile-daemon.am
|
|
||||||
@@ -60,6 +60,7 @@ systemdunit_service_file_names = \
|
|
||||||
rpm-ostreed-automatic.service \
|
|
||||||
rpm-ostree-bootstatus.service \
|
|
||||||
rpm-ostree-countme.service \
|
|
||||||
+ rpm-ostree-fix-shadow-mode.service \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
systemdunit_service_files = $(addprefix $(srcdir)/src/daemon/,$(systemdunit_service_file_names))
|
|
||||||
diff --git a/packaging/rpm-ostree.spec.in b/packaging/rpm-ostree.spec.in
|
|
||||||
index e83db7f3..cbe3e031 100644
|
|
||||||
--- a/packaging/rpm-ostree.spec.in
|
|
||||||
+++ b/packaging/rpm-ostree.spec.in
|
|
||||||
@@ -237,6 +237,11 @@ $PYTHON autofiles.py > files.devel \
|
|
||||||
# Setup rpm-ostree-countme.timer according to presets
|
|
||||||
%post
|
|
||||||
%systemd_post rpm-ostree-countme.timer
|
|
||||||
+# Only enable on rpm-ostree based systems and manually force unit enablement to
|
|
||||||
+# explicitly ignore presets for this security fix
|
|
||||||
+if [ -e /run/ostree-booted ]; then
|
|
||||||
+ ln -snf /usr/lib/systemd/system/rpm-ostree-fix-shadow-mode.service /usr/lib/systemd/system/multi-user.target.wants/
|
|
||||||
+fi
|
|
||||||
|
|
||||||
%preun
|
|
||||||
%systemd_preun rpm-ostree-countme.timer
|
|
||||||
diff --git a/src/daemon/rpm-ostree-fix-shadow-mode.service b/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..4aea7462
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
@@ -0,0 +1,19 @@
|
|
||||||
+[Unit]
|
|
||||||
+# rpm-ostree v2023.6 introduced a permission issue on `/etc/[g]shadow[-]`.
|
|
||||||
+# This makes sure to fix permissions on systems that were deployed with the wrong permissions.
|
|
||||||
+Description=Update permissions for /etc/shadow
|
|
||||||
+Documentation=https://github.com/coreos/rpm-ostree-ghsa-2m76-cwhg-7wv6
|
|
||||||
+ConditionPathExists=!/etc/.rpm-ostree-shadow-mode-fixed.stamp
|
|
||||||
+ConditionPathExists=/run/ostree-booted
|
|
||||||
+# Make sure this is started before any unprivileged (interactive) user has access to the system.
|
|
||||||
+Before=systemd-user-sessions.service
|
|
||||||
+
|
|
||||||
+[Service]
|
|
||||||
+Type=oneshot
|
|
||||||
+ExecStart=chmod --verbose 0000 /etc/shadow /etc/gshadow
|
|
||||||
+ExecStart=-chmod --verbose 0000 /etc/shadow- /etc/gshadow-
|
|
||||||
+ExecStart=touch /etc/.rpm-ostree-shadow-mode-fixed.stamp
|
|
||||||
+RemainAfterExit=yes
|
|
||||||
+
|
|
||||||
+[Install]
|
|
||||||
+WantedBy=multi-user.target
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
@ -1,314 +0,0 @@
|
|||||||
From 1ec5618144e2d5e76caedba9cdcddb2d7ca1d8f7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Colin Walters <walters@verbum.org>
|
|
||||||
Date: Fri, 12 Apr 2024 12:59:54 -0400
|
|
||||||
Subject: [PATCH 3/3] shadow: Adjust all deployments
|
|
||||||
|
|
||||||
It was pointed out that in the previous change here we missed
|
|
||||||
the fact that the previous deployments were accessible.
|
|
||||||
|
|
||||||
- Move the logic into Rust, adding unit tests
|
|
||||||
- Change the code to iterate over all deployments
|
|
||||||
- Add an integration test too
|
|
||||||
|
|
||||||
Note: A likely future enhancement here will be to finally
|
|
||||||
deny unprivileged access to non-default roots; cc
|
|
||||||
https://github.com/ostreedev/ostree/issues/3211
|
|
||||||
---
|
|
||||||
rust/src/lib.rs | 2 +-
|
|
||||||
rust/src/main.rs | 1 +
|
|
||||||
rust/src/passwd.rs | 124 ++++++++++++++++++
|
|
||||||
src/daemon/rpm-ostree-fix-shadow-mode.service | 12 +-
|
|
||||||
tests/kolainst/destructive/shadow | 80 +++++++++++
|
|
||||||
5 files changed, 214 insertions(+), 5 deletions(-)
|
|
||||||
create mode 100755 tests/kolainst/destructive/shadow
|
|
||||||
|
|
||||||
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
|
|
||||||
index e244158b..a65e669b 100644
|
|
||||||
--- a/rust/src/lib.rs
|
|
||||||
+++ b/rust/src/lib.rs
|
|
||||||
@@ -979,7 +979,7 @@ mod normalization;
|
|
||||||
mod origin;
|
|
||||||
mod ostree_prepareroot;
|
|
||||||
pub(crate) use self::origin::*;
|
|
||||||
-mod passwd;
|
|
||||||
+pub mod passwd;
|
|
||||||
use passwd::*;
|
|
||||||
mod console_progress;
|
|
||||||
pub(crate) use self::console_progress::*;
|
|
||||||
diff --git a/rust/src/main.rs b/rust/src/main.rs
|
|
||||||
index 5a3c04d0..bf10d45d 100644
|
|
||||||
--- a/rust/src/main.rs
|
|
||||||
+++ b/rust/src/main.rs
|
|
||||||
@@ -28,6 +28,7 @@ async fn inner_async_main(args: Vec<String>) -> Result<i32> {
|
|
||||||
match *arg {
|
|
||||||
// Add custom Rust commands here, and also in `libmain.cxx` if user-visible.
|
|
||||||
"countme" => rpmostree_rust::countme::entrypoint(args).map(|_| 0),
|
|
||||||
+ "fix-shadow-perms" => rpmostree_rust::passwd::fix_shadow_perms_entrypoint(args).map(|_| 0),
|
|
||||||
"cliwrap" => rpmostree_rust::cliwrap::entrypoint(args).map(|_| 0),
|
|
||||||
// A hidden wrapper to intercept some binaries in RPM scriptlets.
|
|
||||||
"scriptlet-intercept" => builtins::scriptlet_intercept::entrypoint(args).map(|_| 0),
|
|
||||||
diff --git a/rust/src/passwd.rs b/rust/src/passwd.rs
|
|
||||||
index a64f6468..f0a6da31 100644
|
|
||||||
--- a/rust/src/passwd.rs
|
|
||||||
+++ b/rust/src/passwd.rs
|
|
||||||
@@ -30,6 +30,10 @@ const DEFAULT_MODE: u32 = 0o644;
|
|
||||||
static DEFAULT_PERMS: Lazy<Permissions> = Lazy::new(|| Permissions::from_mode(DEFAULT_MODE));
|
|
||||||
static PWGRP_SHADOW_FILES: &[&str] = &["shadow", "gshadow", "subuid", "subgid"];
|
|
||||||
static USRLIB_PWGRP_FILES: &[&str] = &["passwd", "group"];
|
|
||||||
+// This stamp file signals the original fix which only changed the booted deployment
|
|
||||||
+const SHADOW_MODE_FIXED_STAMP_OLD: &str = "etc/.rpm-ostree-shadow-mode-fixed.stamp";
|
|
||||||
+// And this one is written by the newer logic that changes all deployments
|
|
||||||
+const SHADOW_MODE_FIXED_STAMP: &str = "etc/.rpm-ostree-shadow-mode-fixed2.stamp";
|
|
||||||
|
|
||||||
// Lock/backup files that should not be in the base commit (TODO fix).
|
|
||||||
static PWGRP_LOCK_AND_BACKUP_FILES: &[&str] = &[
|
|
||||||
@@ -363,6 +367,86 @@ impl PasswdKind {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+/// Due to a prior bug, the build system had some deployments with a world-readable
|
|
||||||
+/// shadow file. This fixes a given deployment.
|
|
||||||
+#[context("Fixing shadow permissions")]
|
|
||||||
+pub(crate) fn fix_shadow_perms_in_root(root: &Dir) -> Result<bool> {
|
|
||||||
+ let zero_perms = Permissions::from_mode(0);
|
|
||||||
+ let mut changed = false;
|
|
||||||
+ for path in ["etc/shadow", "etc/shadow-", "etc/gshadow", "etc/gshadow-"] {
|
|
||||||
+ let metadata = if let Some(meta) = root
|
|
||||||
+ .symlink_metadata_optional(path)
|
|
||||||
+ .context("Querying metadata")?
|
|
||||||
+ {
|
|
||||||
+ meta
|
|
||||||
+ } else {
|
|
||||||
+ tracing::debug!("No path {path}");
|
|
||||||
+ continue;
|
|
||||||
+ };
|
|
||||||
+ let mode = metadata.mode() & !libc::S_IFMT;
|
|
||||||
+ // Don't touch the file if it's already correct
|
|
||||||
+ if mode == 0 {
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ let f = root.open(path).with_context(|| format!("Opening {path}"))?;
|
|
||||||
+ f.set_permissions(zero_perms.clone())
|
|
||||||
+ .with_context(|| format!("chmod: {path}"))?;
|
|
||||||
+ println!("Adjusted mode for {path}");
|
|
||||||
+ changed = true;
|
|
||||||
+ }
|
|
||||||
+ // Write our stamp file
|
|
||||||
+ root.write(SHADOW_MODE_FIXED_STAMP, "")
|
|
||||||
+ .context(SHADOW_MODE_FIXED_STAMP)?;
|
|
||||||
+ // And clean up the old one
|
|
||||||
+ root.remove_file_optional(SHADOW_MODE_FIXED_STAMP_OLD)
|
|
||||||
+ .with_context(|| format!("Removing old {SHADOW_MODE_FIXED_STAMP_OLD}"))?;
|
|
||||||
+ Ok(changed)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/// Due to a prior bug, the build system had some deployments with a world-readable
|
|
||||||
+/// shadow file. This fixes all deployments.
|
|
||||||
+pub(crate) fn fix_shadow_perms_in_sysroot(sysroot: &ostree::Sysroot) -> Result<bool> {
|
|
||||||
+ let deployments = sysroot.deployments();
|
|
||||||
+ // TODO add a nicer api for this to ostree-rs
|
|
||||||
+ let sysroot_fd =
|
|
||||||
+ Dir::reopen_dir(unsafe { &std::os::fd::BorrowedFd::borrow_raw(sysroot.fd()) })?;
|
|
||||||
+ let mut changed = false;
|
|
||||||
+ for deployment in deployments {
|
|
||||||
+ let path = sysroot.deployment_dirpath(&deployment);
|
|
||||||
+ let dir = sysroot_fd.open_dir(&path)?;
|
|
||||||
+ if fix_shadow_perms_in_root(&dir)
|
|
||||||
+ .with_context(|| format!("Deployment index={}", deployment.index()))?
|
|
||||||
+ {
|
|
||||||
+ println!(
|
|
||||||
+ "Adjusted shadow files in deployment index={} {}.{}",
|
|
||||||
+ deployment.index(),
|
|
||||||
+ deployment.csum(),
|
|
||||||
+ deployment.bootserial()
|
|
||||||
+ );
|
|
||||||
+ changed = true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ Ok(changed)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/// The main entrypoint for updating /etc/{,g}shadow permissions across
|
|
||||||
+/// all deployments.
|
|
||||||
+pub fn fix_shadow_perms_entrypoint(_args: &[&str]) -> Result<()> {
|
|
||||||
+ let cancellable = gio::Cancellable::NONE;
|
|
||||||
+ let sysroot = ostree::Sysroot::new_default();
|
|
||||||
+ sysroot.set_mount_namespace_in_use();
|
|
||||||
+ sysroot.lock()?;
|
|
||||||
+ sysroot.load(cancellable)?;
|
|
||||||
+ let changed = fix_shadow_perms_in_sysroot(&sysroot)?;
|
|
||||||
+ if changed {
|
|
||||||
+ // We already printed per deployment, so this one is just
|
|
||||||
+ // a debug-level log.
|
|
||||||
+ tracing::debug!("Updated shadow/gshadow permissions");
|
|
||||||
+ }
|
|
||||||
+ sysroot.unlock();
|
|
||||||
+ Ok(())
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
// This function writes the static passwd/group data from the treefile to the
|
|
||||||
// target root filesystem.
|
|
||||||
fn write_data_from_treefile(
|
|
||||||
@@ -1070,3 +1154,43 @@ impl PasswdEntries {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+#[test]
|
|
||||||
+fn test_shadow_perms() -> Result<()> {
|
|
||||||
+ let root = &cap_tempfile::tempdir(cap_std::ambient_authority())?;
|
|
||||||
+ root.create_dir("etc")?;
|
|
||||||
+ root.write("etc/shadow", "some shadow")?;
|
|
||||||
+ root.write("etc/gshadow", "some gshadow")?;
|
|
||||||
+ root.set_permissions("etc/gshadow", Permissions::from_mode(0))?;
|
|
||||||
+
|
|
||||||
+ assert!(fix_shadow_perms_in_root(root)?);
|
|
||||||
+ assert!(!root.try_exists(SHADOW_MODE_FIXED_STAMP_OLD)?);
|
|
||||||
+ assert!(root.try_exists(SHADOW_MODE_FIXED_STAMP)?);
|
|
||||||
+ // Verify idempotence
|
|
||||||
+ assert!(!fix_shadow_perms_in_root(root)?);
|
|
||||||
+ assert!(!root.try_exists(SHADOW_MODE_FIXED_STAMP_OLD)?);
|
|
||||||
+ assert!(root.try_exists(SHADOW_MODE_FIXED_STAMP)?);
|
|
||||||
+
|
|
||||||
+ Ok(())
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#[test]
|
|
||||||
+/// Verify the scenario of updating from a previously fixed root
|
|
||||||
+fn test_shadow_perms_from_orig_fix() -> Result<()> {
|
|
||||||
+ let root = &cap_tempfile::tempdir(cap_std::ambient_authority())?;
|
|
||||||
+ root.create_dir("etc")?;
|
|
||||||
+ root.write("etc/shadow", "some shadow")?;
|
|
||||||
+ root.set_permissions("etc/shadow", Permissions::from_mode(0))?;
|
|
||||||
+ root.write("etc/gshadow", "some gshadow")?;
|
|
||||||
+ root.set_permissions("etc/gshadow", Permissions::from_mode(0))?;
|
|
||||||
+ // Write the original stamp file
|
|
||||||
+ root.write(SHADOW_MODE_FIXED_STAMP_OLD, "")?;
|
|
||||||
+
|
|
||||||
+ // No changes
|
|
||||||
+ assert!(!fix_shadow_perms_in_root(root)?);
|
|
||||||
+ // Except we should have updated to the new stamp file
|
|
||||||
+ assert!(!root.try_exists(SHADOW_MODE_FIXED_STAMP_OLD)?);
|
|
||||||
+ assert!(root.try_exists(SHADOW_MODE_FIXED_STAMP)?);
|
|
||||||
+
|
|
||||||
+ Ok(())
|
|
||||||
+}
|
|
||||||
diff --git a/src/daemon/rpm-ostree-fix-shadow-mode.service b/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
index 4aea7462..121bc74e 100644
|
|
||||||
--- a/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
+++ b/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
@@ -3,17 +3,21 @@
|
|
||||||
# This makes sure to fix permissions on systems that were deployed with the wrong permissions.
|
|
||||||
Description=Update permissions for /etc/shadow
|
|
||||||
Documentation=https://github.com/coreos/rpm-ostree-ghsa-2m76-cwhg-7wv6
|
|
||||||
-ConditionPathExists=!/etc/.rpm-ostree-shadow-mode-fixed.stamp
|
|
||||||
+# This new stamp file is written by the Rust code, and obsoletes
|
|
||||||
+# the old /etc/.rpm-ostree-shadow-mode-fixed.stamp
|
|
||||||
+ConditionPathExists=!/etc/.rpm-ostree-shadow-mode-fixed2.stamp
|
|
||||||
ConditionPathExists=/run/ostree-booted
|
|
||||||
+# Because we read the sysroot
|
|
||||||
+RequiresMountsFor=/boot
|
|
||||||
# Make sure this is started before any unprivileged (interactive) user has access to the system.
|
|
||||||
Before=systemd-user-sessions.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
-ExecStart=chmod --verbose 0000 /etc/shadow /etc/gshadow
|
|
||||||
-ExecStart=-chmod --verbose 0000 /etc/shadow- /etc/gshadow-
|
|
||||||
-ExecStart=touch /etc/.rpm-ostree-shadow-mode-fixed.stamp
|
|
||||||
+ExecStart=rpm-ostree fix-shadow-perms
|
|
||||||
RemainAfterExit=yes
|
|
||||||
+# So we can remount /sysroot writable in our own namespace
|
|
||||||
+MountFlags=slave
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
diff --git a/tests/kolainst/destructive/shadow b/tests/kolainst/destructive/shadow
|
|
||||||
new file mode 100755
|
|
||||||
index 00000000..7caf84c0
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tests/kolainst/destructive/shadow
|
|
||||||
@@ -0,0 +1,80 @@
|
|
||||||
+#!/bin/bash
|
|
||||||
+#
|
|
||||||
+# Copyright (C) 2024 Red Hat Inc.
|
|
||||||
+#
|
|
||||||
+# This library is free software; you can redistribute it and/or
|
|
||||||
+# modify it under the terms of the GNU Lesser General Public
|
|
||||||
+# License as published by the Free Software Foundation; either
|
|
||||||
+# version 2 of the License, or (at your option) any later version.
|
|
||||||
+#
|
|
||||||
+# This library is distributed in the hope that it will be useful,
|
|
||||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+# Lesser General Public License for more details.
|
|
||||||
+#
|
|
||||||
+# You should have received a copy of the GNU Lesser General Public
|
|
||||||
+# License along with this library; if not, write to the
|
|
||||||
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
+# Boston, MA 02111-1307, USA.
|
|
||||||
+
|
|
||||||
+set -euo pipefail
|
|
||||||
+
|
|
||||||
+. ${KOLA_EXT_DATA}/libtest.sh
|
|
||||||
+
|
|
||||||
+set -x
|
|
||||||
+
|
|
||||||
+cd $(mktemp -d)
|
|
||||||
+
|
|
||||||
+service=rpm-ostree-fix-shadow-mode.service
|
|
||||||
+stamp=/etc/.rpm-ostree-shadow-mode-fixed2.stamp
|
|
||||||
+
|
|
||||||
+case "${AUTOPKGTEST_REBOOT_MARK:-}" in
|
|
||||||
+"")
|
|
||||||
+
|
|
||||||
+libtest_prepare_fully_offline
|
|
||||||
+libtest_enable_repover 0
|
|
||||||
+
|
|
||||||
+systemctl status ${service} || true
|
|
||||||
+rm -vf /etc/.rpm-ostree-shadow-mode*
|
|
||||||
+chmod 0644 /etc/gshadow
|
|
||||||
+
|
|
||||||
+# Verify running the service once fixes things
|
|
||||||
+systemctl restart $service
|
|
||||||
+assert_has_file "${stamp}"
|
|
||||||
+assert_streq "$(stat -c '%f' /etc/gshadow)" 8000
|
|
||||||
+
|
|
||||||
+# Now *undo* the fix, so that the current (then old) deployment
|
|
||||||
+# is broken still, and ensure after reboot that it's fixed
|
|
||||||
+# in both.
|
|
||||||
+
|
|
||||||
+chmod 0644 /etc/gshadow
|
|
||||||
+rm -vf /etc/.rpm-ostree*
|
|
||||||
+
|
|
||||||
+booted_commit=$(rpm-ostree status --json | jq -r '.deployments[0].checksum')
|
|
||||||
+ostree refs ${booted_commit} --create vmcheck2
|
|
||||||
+rpm-ostree rebase :vmcheck2
|
|
||||||
+
|
|
||||||
+/tmp/autopkgtest-reboot "1"
|
|
||||||
+;;
|
|
||||||
+"1")
|
|
||||||
+
|
|
||||||
+systemctl status $service
|
|
||||||
+assert_has_file "${stamp}"
|
|
||||||
+
|
|
||||||
+verified=0
|
|
||||||
+for f in $(ls /ostree/deploy/*/deploy/*/etc/{,g}shadow{,-}); do
|
|
||||||
+ verified=$(($verified + 1))
|
|
||||||
+ assert_streq "$(stat -c '%f' $f)" 8000
|
|
||||||
+ echo "ok ${f}"
|
|
||||||
+done
|
|
||||||
+assert_streq "$verified" 8
|
|
||||||
+
|
|
||||||
+journalctl -b -u $service --grep="Adjusted shadow files in deployment" | tee out.txt
|
|
||||||
+assert_streq "$(wc -l < out.txt)" 2
|
|
||||||
+
|
|
||||||
+echo "ok shadow"
|
|
||||||
+
|
|
||||||
+;;
|
|
||||||
+*) echo "unexpected mark: ${AUTOPKGTEST_REBOOT_MARK}"; exit 1;;
|
|
||||||
+
|
|
||||||
+esac
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
|||||||
From 6714c34bae041c036277ddb509af2b4135b759d5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jonathan Lebon <jonathan@jlebon.com>
|
|
||||||
Date: Tue, 7 May 2024 10:05:03 -0400
|
|
||||||
Subject: [PATCH 1/1] core: also wrap `kernel-install` for scriptlets
|
|
||||||
|
|
||||||
It's confusing right now how specifically for the kernel, one has to use
|
|
||||||
this obscure `rpm-ostree cliwrap install-to-root /` command to make it
|
|
||||||
work. Let's just always enable it: in the client-side layering case, we
|
|
||||||
don't run kernel scriptlets anyway so the wrapper is unused, and in the
|
|
||||||
container case, this will allow users to not have to enable cliwrap and
|
|
||||||
have it leak into their derived image.
|
|
||||||
|
|
||||||
I guess in theory, this should also allow us to *stop* ignoring kernel
|
|
||||||
scriptlets and rely on this instead, though let's leave that for a
|
|
||||||
separate investigation.
|
|
||||||
|
|
||||||
Closes: #4949
|
|
||||||
---
|
|
||||||
rust/src/core.rs | 18 +++++++++++++++++-
|
|
||||||
src/libpriv/kernel-install-wrapper.sh | 9 +++++++++
|
|
||||||
2 files changed, 26 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 src/libpriv/kernel-install-wrapper.sh
|
|
||||||
|
|
||||||
diff --git a/rust/src/core.rs b/rust/src/core.rs
|
|
||||||
index 8cd1ee03..ec24ed99 100644
|
|
||||||
--- a/rust/src/core.rs
|
|
||||||
+++ b/rust/src/core.rs
|
|
||||||
@@ -44,6 +44,8 @@ const USERADD_PATH: &str = "usr/sbin/useradd";
|
|
||||||
const USERADD_WRAPPER: &[u8] = include_bytes!("../../src/libpriv/useradd-wrapper.sh");
|
|
||||||
const USERMOD_PATH: &str = "usr/sbin/usermod";
|
|
||||||
const USERMOD_WRAPPER: &[u8] = include_bytes!("../../src/libpriv/usermod-wrapper.sh");
|
|
||||||
+const KERNEL_INSTALL_PATH: &str = "usr/bin/kernel-install";
|
|
||||||
+const KERNEL_INSTALL_WRAPPER: &[u8] = include_bytes!("../../src/libpriv/kernel-install-wrapper.sh");
|
|
||||||
|
|
||||||
const RPMOSTREE_CORE_STAGED_RPMS_DIR: &str = "rpm-ostree/staged-rpms";
|
|
||||||
|
|
||||||
@@ -143,6 +145,7 @@ impl FilesystemScriptPrep {
|
|
||||||
(SYSTEMCTL_PATH, SYSTEMCTL_WRAPPER),
|
|
||||||
(USERADD_PATH, USERADD_WRAPPER),
|
|
||||||
(USERMOD_PATH, USERMOD_WRAPPER),
|
|
||||||
+ (KERNEL_INSTALL_PATH, KERNEL_INSTALL_WRAPPER),
|
|
||||||
];
|
|
||||||
|
|
||||||
fn saved_name(name: &str) -> String {
|
|
||||||
@@ -436,7 +439,7 @@ mod test {
|
|
||||||
// Replaced usermod.
|
|
||||||
{
|
|
||||||
let original_usermod = "original usermod";
|
|
||||||
- d.atomic_write_with_perms(super::USERMOD_PATH, original_usermod, mode)?;
|
|
||||||
+ d.atomic_write_with_perms(super::USERMOD_PATH, original_usermod, mode.clone())?;
|
|
||||||
let contents = d.read_to_string(super::USERMOD_PATH)?;
|
|
||||||
assert_eq!(contents, original_usermod);
|
|
||||||
let mut g = super::prepare_filesystem_script_prep(d.as_raw_fd())?;
|
|
||||||
@@ -446,6 +449,19 @@ mod test {
|
|
||||||
let contents = d.read_to_string(super::USERMOD_PATH)?;
|
|
||||||
assert_eq!(contents, original_usermod);
|
|
||||||
}
|
|
||||||
+ // Replaced kernel-install.
|
|
||||||
+ {
|
|
||||||
+ let original_kernel_install = "original kernel_install";
|
|
||||||
+ d.atomic_write_with_perms(super::KERNEL_INSTALL_PATH, original_kernel_install, mode)?;
|
|
||||||
+ let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
|
|
||||||
+ assert_eq!(contents, original_kernel_install);
|
|
||||||
+ let mut g = super::prepare_filesystem_script_prep(d.as_raw_fd())?;
|
|
||||||
+ let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
|
|
||||||
+ assert_eq!(contents.as_bytes(), super::KERNEL_INSTALL_WRAPPER);
|
|
||||||
+ g.undo()?;
|
|
||||||
+ let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
|
|
||||||
+ assert_eq!(contents, original_kernel_install);
|
|
||||||
+ }
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/src/libpriv/kernel-install-wrapper.sh b/src/libpriv/kernel-install-wrapper.sh
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..4cfb605b
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/src/libpriv/kernel-install-wrapper.sh
|
|
||||||
@@ -0,0 +1,9 @@
|
|
||||||
+#!/usr/bin/bash
|
|
||||||
+# Used in the container layering path to make kernel replacements Just Work
|
|
||||||
+# without having to enable cliwrap first. If cliwrap is enabled, then this will
|
|
||||||
+# technically override the cliwrap wrapper, but the script is exactly the same.
|
|
||||||
+# This wrapper is technically also installed when doing client-side layering,
|
|
||||||
+# but we already ignore kernel scriptlets there anyway.
|
|
||||||
+# See also https://github.com/coreos/rpm-ostree/issues/4949
|
|
||||||
+
|
|
||||||
+exec /usr/bin/rpm-ostree cliwrap kernel-install "$@"
|
|
||||||
--
|
|
||||||
2.45.0
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
From 82cfc5491b3c670dd3d0abc0b30758622c958299 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Joseph Marrero Corchado <jmarrero@redhat.com>
|
|
||||||
Date: Thu, 2 May 2024 08:57:45 -0400
|
|
||||||
Subject: [PATCH] rpm-ostree-fix-shadow-mode.service: don't run if OS is not
|
|
||||||
installed
|
|
||||||
|
|
||||||
Co-authored-by: Jonathan Lebon <jonathan@jlebon.com>
|
|
||||||
---
|
|
||||||
src/daemon/rpm-ostree-fix-shadow-mode.service | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/daemon/rpm-ostree-fix-shadow-mode.service b/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
index 121bc74e..f2983032 100644
|
|
||||||
--- a/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
+++ b/src/daemon/rpm-ostree-fix-shadow-mode.service
|
|
||||||
@@ -7,6 +7,8 @@ Documentation=https://github.com/coreos/rpm-ostree-ghsa-2m76-cwhg-7wv6
|
|
||||||
# the old /etc/.rpm-ostree-shadow-mode-fixed.stamp
|
|
||||||
ConditionPathExists=!/etc/.rpm-ostree-shadow-mode-fixed2.stamp
|
|
||||||
ConditionPathExists=/run/ostree-booted
|
|
||||||
+# Filter out non-traditional ostree setups (e.g. live boots)
|
|
||||||
+ConditionKernelCommandLine=ostree
|
|
||||||
# Because we read the sysroot
|
|
||||||
RequiresMountsFor=/boot
|
|
||||||
# Make sure this is started before any unprivileged (interactive) user has access to the system.
|
|
||||||
--
|
|
||||||
2.45.2
|
|
||||||
|
|
@ -3,20 +3,16 @@
|
|||||||
|
|
||||||
Summary: Hybrid image/package system
|
Summary: Hybrid image/package system
|
||||||
Name: rpm-ostree
|
Name: rpm-ostree
|
||||||
Version: 2024.3
|
Version: 2024.7
|
||||||
Release: 5%{?dist}
|
Release: 3%{?dist}
|
||||||
License: LGPLv2+
|
License: LGPLv2+
|
||||||
URL: https://github.com/coreos/rpm-ostree
|
URL: https://github.com/coreos/rpm-ostree
|
||||||
# This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot"
|
# This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot"
|
||||||
# in the upstream git. It also contains vendored Rust sources.
|
# 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
|
Source0: https://github.com/coreos/rpm-ostree/releases/download/v%{version}/rpm-ostree-%{version}.tar.xz
|
||||||
|
|
||||||
Patch0: 0001-cliwrap-rpm-mark-eval-E-as-safe.patch
|
Patch0: 0001-core-Fix-Coverity-WRAPPER_ESCAPE.patch
|
||||||
Patch1: 0001-passwd-create-etc-g-shadow-with-mode-0.patch
|
Patch1: 0001-treefile-Add-ignore-devices.patch
|
||||||
Patch2: 0002-unit-chmod-etc-g-shadow-to-0000.patch
|
|
||||||
Patch3: 0003-shadow-Adjust-all-deployments.patch
|
|
||||||
Patch4: 0004-core-also-wrap-kernel-install-for-scriptlets.patch
|
|
||||||
Patch5: 0005-rpm-ostree-fix-shadow-mode.service-don-t-run-if-OS-i.patch
|
|
||||||
|
|
||||||
ExclusiveArch: %{rust_arches}
|
ExclusiveArch: %{rust_arches}
|
||||||
|
|
||||||
@ -251,21 +247,36 @@ fi
|
|||||||
%files devel -f files.devel
|
%files devel -f files.devel
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Tue Aug 20 2024 Huijing Hei <hhei@fedoraproject.org> - 2024.3-5
|
* Thu Oct 17 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.7-3
|
||||||
- Backport https://github.com/coreos/rpm-ostree/pull/4944
|
- Backport https://github.com/coreos/rpm-ostree/pull/5051
|
||||||
Resolves: #RHEL-55249
|
Resolves: #RHEL-59716
|
||||||
|
|
||||||
* Fri May 10 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-4
|
* Thu Aug 15 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.7-2
|
||||||
- Backport https://github.com/coreos/rpm-ostree/pull/4950
|
- Backport https://github.com/coreos/rpm-ostree/pull/5051
|
||||||
Resolves: #RHEL-36085
|
Resolves: #RHEL-53871
|
||||||
|
|
||||||
* Tue Apr 16 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-3
|
* Tue Aug 09 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.7-1
|
||||||
|
- Rebase to 2024.7
|
||||||
|
Resolves: #RHEL-53871
|
||||||
|
|
||||||
|
* Tue May 21 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.5-1
|
||||||
|
- Rebase to 2024.6
|
||||||
|
Resolves: #RHEL-29339
|
||||||
|
|
||||||
|
* Mon Apr 15 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.5-1
|
||||||
|
- Rebase to 2024.5
|
||||||
|
Adds fix for https://github.com/coreos/rpm-ostree/security/advisories/GHSA-2m76-cwhg-7wv6
|
||||||
|
Resolves: #RHEL-30415
|
||||||
|
|
||||||
|
* Tue Apr 09 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.4-4
|
||||||
- Backport https://github.com/coreos/rpm-ostree/security/advisories/GHSA-2m76-cwhg-7wv6
|
- Backport https://github.com/coreos/rpm-ostree/security/advisories/GHSA-2m76-cwhg-7wv6
|
||||||
Resolves: #RHEL-31852
|
|
||||||
|
|
||||||
* Fri Apr 05 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-2
|
* Thu Mar 21 2024 Colin Walters <walters@verbum.org> - 2024.4-3
|
||||||
- Backport https://github.com/coreos/rpm-ostree/security/advisories/GHSA-2m76-cwhg-7wv6
|
- Backport patch to fix https://issues.redhat.com/browse/RHEL-29559
|
||||||
Resolves: #RHEL-31852
|
|
||||||
|
* Fri Mar 15 2024 Colin Walters <walters@verbum.org> - 2024.4-2
|
||||||
|
- https://github.com/coreos/rpm-ostree/releases/tag/v2024.4
|
||||||
|
Resolves: #RHEL-29339
|
||||||
|
|
||||||
* Sun Feb 25 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-1
|
* Sun Feb 25 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-1
|
||||||
- https://github.com/coreos/rpm-ostree/releases/tag/v2024.3
|
- https://github.com/coreos/rpm-ostree/releases/tag/v2024.3
|
||||||
|
Loading…
Reference in New Issue
Block a user