- passwd: create /etc/[g]shadow
with mode 0
- unit: chmod /etc/[g]shadow[-] to 0000 - shadow: Adjust all deployments - ci/test-container: move URL definitions to the top
This commit is contained in:
parent
90d969dfc9
commit
3b57387348
157
SOURCES/0001-passwd-create-etc-gshadow-with-mode-0.patch
Normal file
157
SOURCES/0001-passwd-create-etc-gshadow-with-mode-0.patch
Normal file
@ -0,0 +1,157 @@
|
||||
From b1d88ce602107fa97bb60bc8bcd1460472ddafa0 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/2] 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 99004ac4d5..d897da678d 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 0a7517608f..3f7c6d8ae5 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
|
||||
|
||||
|
||||
From 26a3922979dc2c18a479d9b9b7b51c8af4e5da47 Mon Sep 17 00:00:00 2001
|
||||
From: jbtrystram <jbtrystram@redhat.com>
|
||||
Date: Thu, 21 Mar 2024 17:27:21 +0100
|
||||
Subject: [PATCH 2/2] 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 4233d90db1..f96f49a952 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 8aa9afaaa7..f734f676c3 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 0000000000..4aea7462ec
|
||||
--- /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
|
311
SOURCES/0002-shadow-adjust-all-deployments.patch
Normal file
311
SOURCES/0002-shadow-adjust-all-deployments.patch
Normal file
@ -0,0 +1,311 @@
|
||||
From d40ba771b80c4e9fd86e3f4b8a438112dcaf9393 Mon Sep 17 00:00:00 2001
|
||||
From: Colin Walters <walters@verbum.org>
|
||||
Date: Fri, 12 Apr 2024 12:59:54 -0400
|
||||
Subject: [PATCH] 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 0255b1e3ab..f1d971762a 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 5a3c04d0e0..bf10d45dcc 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 d897da678d..213c271c7e 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 4aea7462ec..121bc74ef6 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 0000000000..7caf84c051
|
||||
--- /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
|
@ -0,0 +1,88 @@
|
||||
From 2a8017c3e1fb24d42520df21eab3f157e8469312 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Lebon <jonathan@jlebon.com>
|
||||
Date: Tue, 7 May 2024 10:05:03 -0400
|
||||
Subject: [PATCH] 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 11c2d9822a..02255a8481 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 0000000000..4cfb605b2b
|
||||
--- /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 "$@"
|
@ -4,7 +4,7 @@
|
||||
Summary: Hybrid image/package system
|
||||
Name: rpm-ostree
|
||||
Version: 2024.3
|
||||
Release: 1%{?dist}
|
||||
Release: 4%{?dist}.alma.1
|
||||
License: LGPLv2+
|
||||
URL: https://github.com/coreos/rpm-ostree
|
||||
# This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot"
|
||||
@ -13,6 +13,14 @@ Source0: https://github.com/coreos/rpm-ostree/releases/download/v%{version}/rpm-
|
||||
|
||||
Patch0: 0001-cliwrap-rpm-mark-eval-E-as-safe.patch
|
||||
|
||||
# Patches were taken from:
|
||||
# https://github.com/coreos/rpm-ostree/pull/4911
|
||||
Patch1: 0001-passwd-create-etc-gshadow-with-mode-0.patch
|
||||
# https://github.com/coreos/rpm-ostree/pull/4913
|
||||
Patch2: 0002-shadow-adjust-all-deployments.patch
|
||||
# https://github.com/coreos/rpm-ostree/pull/4950
|
||||
Patch3: 0003-citest-container-move-URL-definitions-to-the-top.patch
|
||||
|
||||
ExclusiveArch: %{rust_arches}
|
||||
|
||||
BuildRequires: make
|
||||
@ -231,6 +239,13 @@ $PYTHON autofiles.py > files.devel \
|
||||
'%{_datadir}/gtk-doc/html/*' \
|
||||
'%{_datadir}/gir-1.0/*-1.0.gir'
|
||||
|
||||
%post
|
||||
# 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
|
||||
|
||||
%files -f files
|
||||
%doc COPYING.GPL COPYING.LGPL LICENSE README.md
|
||||
|
||||
@ -239,6 +254,12 @@ $PYTHON autofiles.py > files.devel \
|
||||
%files devel -f files.devel
|
||||
|
||||
%changelog
|
||||
* Sun Feb 25 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-4.alma.1
|
||||
- passwd: create `/etc/[g]shadow` with mode 0
|
||||
- unit: chmod /etc/[g]shadow[-] to 0000
|
||||
- shadow: Adjust all deployments
|
||||
- ci/test-container: move URL definitions to the top
|
||||
|
||||
* Sun Feb 25 2024 Joseph Marrero <jmarrero@fedoraproject.org> - 2024.3-1
|
||||
- https://github.com/coreos/rpm-ostree/releases/tag/v2024.3
|
||||
Backport https://github.com/coreos/rpm-ostree/commit/fe586621e5014d14f92b913338171a02ed29e6cc
|
||||
@ -972,4 +993,3 @@ $PYTHON autofiles.py > files.devel \
|
||||
|
||||
* Fri Mar 07 2014 Colin Walters <walters@verbum.org> - 2014.5-1
|
||||
- Initial package
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user