rpm-ostree/SOURCES/0001-passwd-create-etc-gshadow-with-mode-0.patch
eabdullin 3b57387348 - 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
2024-06-13 16:22:42 +03:00

158 lines
6.5 KiB
Diff

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