diff --git a/SOURCES/1082-execute-make-sure-to-call-into-PAM-after-initializin.patch b/SOURCES/1082-execute-make-sure-to-call-into-PAM-after-initializin.patch new file mode 100644 index 0000000..98ccc2c --- /dev/null +++ b/SOURCES/1082-execute-make-sure-to-call-into-PAM-after-initializin.patch @@ -0,0 +1,64 @@ +From e35327017659a1bf07d68448ce896b96a4ae30f5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 12:24:14 +0100 +Subject: [PATCH] execute: make sure to call into PAM after initializing + resource limits + +We want that pam_limits takes precedence over our settings, after all. + +Fixes: #11386 +(cherry picked from commit ce932d2d331886190dca9d54571d3d99d9fe8cfc) + +Resolves: RHEL-5986 +--- + src/core/execute.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 7e186c948c..ad9f660540 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -3291,7 +3291,24 @@ static int exec_child( + #endif + } + ++ if (needs_sandboxing) { ++ int which_failed; ++ ++ /* Let's set the resource limits before we call into PAM, so that pam_limits wins over what ++ * is set here. (See below.) */ ++ ++ r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed); ++ if (r < 0) { ++ *exit_status = EXIT_LIMITS; ++ return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed)); ++ } ++ } ++ + if (needs_setuid) { ++ ++ /* Let's call into PAM after we set up our own idea of resource limits to that pam_limits ++ * wins here. (See above.) */ ++ + if (context->pam_name && username) { + r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds); + if (r < 0) { +@@ -3413,15 +3430,10 @@ static int exec_child( + + if (needs_sandboxing) { + uint64_t bset; +- int which_failed; +- +- r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed); +- if (r < 0) { +- *exit_status = EXIT_LIMITS; +- return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed)); +- } + +- /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly requested. */ ++ /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly ++ * requested. (Note this is placed after the general resource limit initialization, see ++ * above, in order to take precedence.) */ + if (context->restrict_realtime && !context->rlimit[RLIMIT_RTPRIO]) { + if (setrlimit(RLIMIT_RTPRIO, &RLIMIT_MAKE_CONST(0)) < 0) { + *exit_status = EXIT_LIMITS; diff --git a/SOURCES/1083-pager-also-check-for-SUDO_UID.patch b/SOURCES/1083-pager-also-check-for-SUDO_UID.patch new file mode 100644 index 0000000..48f91fb --- /dev/null +++ b/SOURCES/1083-pager-also-check-for-SUDO_UID.patch @@ -0,0 +1,129 @@ +From 0d84ad9bbb97007f0c998c873db7bc53f8413826 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 17 Jun 2026 15:55:56 +0200 +Subject: [PATCH] pager: also check for $SUDO_UID +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This returns to the original approach proposed in +https://github.com/systemd/systemd/pull/17270. After review, the approach was +changed to use sd_pid_get_owner_uid() instead. Back then, when running in a +typical graphical session, sd_pid_get_owner_uid() would usually return the user +UID, and when running under sudo, geteuid() would return 0, so we'd trigger the +secure path. + +sudo may allocate a new session if is invoked outside of a session (depending +on the PAM config). Since nowadays desktop environments usually start the user +shell through user units, the typical shell in a terminal emulator is not part +of a session, and when sudo is invoked, a new session is allocated, and +sd_pid_get_owner_uid() returns 0 too. Technically, the code still works as +documented in the man page, but in the common case, it doesn't do the expected +thing. + +$ build/test-sd-login |& rg 'get_(owner_uid|cgroup|session)' +sd_pid_get_session(0) → No data available +sd_pid_get_owner_uid(0) → 1000 +sd_pid_get_cgroup(0) → /user.slice/user-1000.slice/user@1000.service/app.slice/app-ghostty-transient-5088.scope/surfaces/556FAF50BA40.scope + +$ sudo build/test-sd-login |& rg 'get_(owner_uid|cgroup|session)' +sd_pid_get_session(0) → c289 +sd_pid_get_owner_uid(0) → 0 +sd_pid_get_cgroup(0) → /user.slice/user-0.slice/session-c289.scope + +I think it's worth checking for sudo because it is a common case used by users. +There obviously are other mechanims, so the man page is extended to say that +only some common mechanisms are supported, and to (again) recommend setting +SYSTEMD_LESSSECURE explicitly. The other option would be to set "secure mode" +by default. But this would create an inconvenience for users doing the right +thing, running systemctl and other tools directly, because then they can't run +privileged commands from the pager, e.g. to save the output to a file. (Or the +user would need to explicitly set SYSTEMD_LESSSECURE. One option would be to +set it always in the environment and to rely on sudo and other tools stripping +it from the environment before running privileged code. But that is also fairly +fragile and it obviously relies on the user doing a complicated setup to +support a fairly common use case. I think this decreases usability of the +system quite a bit. I don't think we should build solutions that work in +priniciple, but are painfully inconvenient in common cases.) + +Fixes https://yeswehack.com/vulnerability-center/reports/346802. + +Also see https://github.com/polkit-org/polkit/pull/562, which adds support for +$SUDO_UID/$SUDO_GID to pkexec. + +(cherry picked from commit cd93478af8b9dc69478d5667f113b67d175090fa) + +Resolves: RHEL-102942 +--- + man/less-variables.xml | 9 +++++++-- + src/basic/pager.c | 29 +++++++++++++++++++---------- + 2 files changed, 26 insertions(+), 12 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index 5f3a53c8dd..e9f1fa0350 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -43,9 +43,14 @@ + false, disabled. If $SYSTEMD_PAGERSECURE is not set at all, secure mode is enabled + if the effective UID is not the same as the owner of the login session, see geteuid2 and +- sd_pid_get_owner_uid3. ++ sd_pid_get_owner_uid3, ++ or when running under ++ sudo8 or similar ++ tools ($SUDO_UID is set). + In secure mode, will be set when invoking the pager, and the pager shall +- disable commands that open or create new files or start new subprocesses. When ++ disable commands that open or create new files or start new subprocesses. Note that this autodetection ++ only covers the most common mechanisms to elevate privileges and is intended as convenience. It is ++ recommended to explicitly set $SYSTEMD_PAGERSECURE or disable the pager. When + $SYSTEMD_PAGERSECURE is not set at all, pagers which are not known to implement + secure mode will not be used. (Currently only + less1 implements +diff --git a/src/basic/pager.c b/src/basic/pager.c +index c7e101235d..bea139a80a 100644 +--- a/src/basic/pager.c ++++ b/src/basic/pager.c +@@ -44,6 +44,22 @@ _noreturn_ static void pager_fallback(void) { + _exit(EXIT_SUCCESS); + } + ++static bool running_with_escalated_privileges(void) { ++ int r; ++ ++ if (getenv("SUDO_UID")) ++ return true; ++ ++ uid_t uid; ++ r = sd_pid_get_owner_uid(0, &uid); ++ if (r < 0) { ++ log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); ++ return true; ++ } ++ ++ return uid != geteuid(); ++} ++ + int pager_open(bool no_pager, bool jump_to_end) { + _cleanup_close_pair_ int fd[2] = { -1, -1 }; + const char *pager; +@@ -113,16 +129,9 @@ int pager_open(bool no_pager, bool jump_to_end) { + * know to be good. */ + int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE"); + bool trust_pager = use_secure_mode >= 0; +- if (use_secure_mode == -ENXIO) { +- uid_t uid; +- +- r = sd_pid_get_owner_uid(0, &uid); +- if (r < 0) +- log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); +- +- use_secure_mode = r < 0 || uid != geteuid(); +- +- } else if (use_secure_mode < 0) { ++ if (use_secure_mode == -ENXIO) ++ use_secure_mode = running_with_escalated_privileges(); ++ else if (use_secure_mode < 0) { + log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m"); + use_secure_mode = true; + } diff --git a/SOURCES/1084-user-sessions-do-not-remove-etc-nologin.patch b/SOURCES/1084-user-sessions-do-not-remove-etc-nologin.patch new file mode 100644 index 0000000..2eca84a --- /dev/null +++ b/SOURCES/1084-user-sessions-do-not-remove-etc-nologin.patch @@ -0,0 +1,77 @@ +From fd2ed473d872003e19179f734a94c07112aa1ebf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sat, 25 Mar 2023 11:34:47 +0100 +Subject: [PATCH] user-sessions: do not remove /etc/nologin + +pam_nologin looks for /etc/nologin and /run/nologin. +user-sessions creates (and removes) /run/nologin, but also removes +/etc/nologin. (This behaviour is unchanged since the introduction +of the binary in e92787416c691c3f34f47349e5eae3fa68eae856.) + +By not removing pam_nologin we fully drop compatibility with PAM < 1.1. +This has the advantage that now /etc/nologin can be used by administrator to +disable user logins, e.g. for extended maintanance. We already specified +PAM >= 1.1.2 as dependency, so this was already covered. + +The makes the code match the man page. + +Fixes #26965. + +(cherry picked from commit a78413baae0e999384b535d327203ebf417b1e24) + +Resolves: RHEL-85520 +--- + src/basic/fileio-label.c | 12 +++++++++--- + src/user-sessions/user-sessions.c | 7 ++----- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c +index 5f8d8af9af..0b52657757 100644 +--- a/src/basic/fileio-label.c ++++ b/src/basic/fileio-label.c +@@ -55,9 +55,15 @@ int fopen_temporary_label(const char *target, + int create_shutdown_run_nologin_or_warn(void) { + int r; + +- /* This is used twice: once in systemd-user-sessions.service, in order to block logins when we actually go +- * down, and once in systemd-logind.service when shutdowns are scheduled, and logins are to be turned off a bit +- * in advance. We use the same wording of the message in both cases. */ ++ /* This is used twice: once in systemd-user-sessions.service, in order to block logins when we ++ * actually go down, and once in systemd-logind.service when shutdowns are scheduled, and logins are ++ * to be turned off a bit in advance. We use the same wording of the message in both cases. ++ * ++ * Traditionally, there was only /etc/nologin, and we managed that. Then, in PAM 1.1 ++ * support for /run/nologin was added as alternative ++ * (https://github.com/linux-pam/linux-pam/commit/e9e593f6ddeaf975b7fe8446d184e6bc387d450b). ++ * 13 years later we stopped managing /etc/nologin, leaving it for the administrator to manage. ++ */ + + r = write_string_file_atomic_label("/run/nologin", + "System is going down. Unprivileged users are not permitted to log in anymore. " +diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c +index 89c4b0005d..8ac4826f83 100644 +--- a/src/user-sessions/user-sessions.c ++++ b/src/user-sessions/user-sessions.c +@@ -12,7 +12,7 @@ + #include "util.h" + + int main(int argc, char*argv[]) { +- int r, k; ++ int r; + + if (argc != 2) { + log_error("This program requires one argument."); +@@ -27,12 +27,9 @@ int main(int argc, char*argv[]) { + + mac_selinux_init(); + ++ /* We only touch /run/nologin. See create_shutdown_run_nologin_or_warn() for details. */ + if (streq(argv[1], "start")) { + r = unlink_or_warn("/run/nologin"); +- k = unlink_or_warn("/etc/nologin"); +- if (k < 0 && r >= 0) +- r = k; +- + } else if (streq(argv[1], "stop")) + r = create_shutdown_run_nologin_or_warn(); + else { diff --git a/SOURCES/1085-core-allow-manager_serialize-to-fail-correctly.patch b/SOURCES/1085-core-allow-manager_serialize-to-fail-correctly.patch new file mode 100644 index 0000000..c0438d7 --- /dev/null +++ b/SOURCES/1085-core-allow-manager_serialize-to-fail-correctly.patch @@ -0,0 +1,134 @@ +From d489e6c6315d20f695d6ed269de15fb3c204d082 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 9 Oct 2018 16:45:33 +0200 +Subject: [PATCH] core: allow manager_serialize() to fail correctly + +If manager_serialize() fails in the middle (which it hopefully doesn't) +make sure to fix up m->n_reloading correctly again so that we don't +leave it > 0 when it really shouldn't be. + +(cherry picked from commit 4daf832afaeac471085e56445a05218217bf5107) + +Resolves: RHEL-112550 +--- + src/core/manager.c | 56 +++++++++++++++++++++++++++++----------------- + 1 file changed, 35 insertions(+), 21 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index f242f0cc00..406dad07b2 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -3099,7 +3099,12 @@ int manager_open_serialization(Manager *m, FILE **_f) { + return 0; + } + +-int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { ++int manager_serialize( ++ Manager *m, ++ FILE *f, ++ FDSet *fds, ++ bool switching_root) { ++ + ManagerTimestamp q; + const char *t; + Iterator i; +@@ -3145,8 +3150,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { + int copy; + + copy = fdset_put_dup(fds, m->notify_fd); +- if (copy < 0) +- return copy; ++ if (copy < 0) { ++ r = copy; ++ goto finish; ++ } + + fprintf(f, "notify-fd=%i\n", copy); + fprintf(f, "notify-socket=%s\n", m->notify_socket); +@@ -3156,8 +3163,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { + int copy; + + copy = fdset_put_dup(fds, m->cgroups_agent_fd); +- if (copy < 0) +- return copy; ++ if (copy < 0) { ++ r = copy; ++ goto finish; ++ } + + fprintf(f, "cgroups-agent-fd=%i\n", copy); + } +@@ -3166,12 +3175,16 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { + int copy0, copy1; + + copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]); +- if (copy0 < 0) +- return copy0; ++ if (copy0 < 0) { ++ r = copy0; ++ goto finish; ++ } + + copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]); +- if (copy1 < 0) +- return copy1; ++ if (copy1 < 0) { ++ r = copy1; ++ goto finish; ++ } + + fprintf(f, "user-lookup=%i %i\n", copy0, copy1); + } +@@ -3180,14 +3193,14 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { + + r = dynamic_user_serialize(m, f, fds); + if (r < 0) +- return r; ++ goto finish; + + manager_serialize_uid_refs(m, f); + manager_serialize_gid_refs(m, f); + + r = exec_runtime_serialize(m, f, fds); + if (r < 0) +- return r; ++ goto finish; + + (void) fputc('\n', f); + +@@ -3200,24 +3213,25 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { + fputc('\n', f); + + r = unit_serialize(u, f, fds, !switching_root); +- if (r < 0) { +- m->n_reloading--; +- return r; +- } ++ if (r < 0) ++ goto finish; + } + +- assert(m->n_reloading > 0); +- m->n_reloading--; +- + r = fflush_and_check(f); + if (r < 0) +- return r; ++ goto finish; + + r = bus_fdset_add_all(m, fds); + if (r < 0) +- return r; ++ goto finish; + +- return 0; ++ r = 0; ++ ++finish: ++ assert(m->n_reloading > 0); ++ m->n_reloading--; ++ ++ return r; + } + + int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index 3ad97f4..b801ed7 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 82%{?dist}.17 +Release: 82%{?dist}.19 # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -1131,6 +1131,10 @@ Patch1078: 1078-job-be-more-careful-when-removing-job-object-from-jo.patch Patch1079: 1079-core-rework-how-we-deserialize-jobs.patch Patch1080: 1080-core-when-a-unit-state-changes-only-propagate-to-job.patch Patch1081: 1081-core-extend-comments-regarding-coldplug-vs.-catchup.patch +Patch1082: 1082-execute-make-sure-to-call-into-PAM-after-initializin.patch +Patch1083: 1083-pager-also-check-for-SUDO_UID.patch +Patch1084: 1084-user-sessions-do-not-remove-etc-nologin.patch +Patch1085: 1085-core-allow-manager_serialize-to-fail-correctly.patch %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 @@ -1757,6 +1761,14 @@ fi %files tests -f .file-list-tests %changelog +* Mon Jul 27 2026 systemd maintenance team - 239-82.19 +- user-sessions: do not remove /etc/nologin (RHEL-85520) +- core: allow manager_serialize() to fail correctly (RHEL-112550) + +* Tue Jul 21 2026 systemd maintenance team - 239-82.18 +- execute: make sure to call into PAM after initializing resource limits (RHEL-5986) +- pager: also check for $SUDO_UID (RHEL-102942) + * Mon May 25 2026 systemd maintenance team - 239-82.17 - job: update job_free() to follow our usual return-NULL style (RHEL-168671) - core: don't track jobs-finishing-during-reload explicitly (RHEL-168671)