From 04f2672d6daf437cb1c50e4bae680b4058683a1d Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Tue, 18 Apr 2023 08:29:34 +0200 Subject: [PATCH] systemd-239-75 Resolves: #2175624,#2176892,#2179309 --- ...always-create-state-file-in-signal-h.patch | 4 +- ...r-move-relinquish-code-into-function.patch | 4 +- ...always-touch-state-file-in-signal-ha.patch | 4 +- ...test-make-TEST-35-LOGIN-stable-again.patch | 299 ++++++++++++++++++ ...LESSSECURE-whenver-we-invoke-a-pager.patch | 113 +++++++ ...s-test-sd_pid_get_owner_uid-moderniz.patch | 264 ++++++++++++++++ ...-secure-when-under-euid-is-changed-o.patch | 198 ++++++++++++ ...erential-shellcheck-workflow-on-push.patch | 49 +++ 0910-ci-codeql-master-main.patch | 34 ++ ...OMEDIUM-error-from-sd_pid_get_cgroup.patch | 30 ++ systemd.spec | 21 +- 11 files changed, 1013 insertions(+), 7 deletions(-) create mode 100644 0905-test-make-TEST-35-LOGIN-stable-again.patch create mode 100644 0906-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch create mode 100644 0907-test-login-always-test-sd_pid_get_owner_uid-moderniz.patch create mode 100644 0908-pager-make-pager-secure-when-under-euid-is-changed-o.patch create mode 100644 0909-ci-trigger-differential-shellcheck-workflow-on-push.patch create mode 100644 0910-ci-codeql-master-main.patch create mode 100644 0911-test-ignore-ENOMEDIUM-error-from-sd_pid_get_cgroup.patch diff --git a/0902-journald-server-always-create-state-file-in-signal-h.patch b/0902-journald-server-always-create-state-file-in-signal-h.patch index b09df96..ed9308c 100644 --- a/0902-journald-server-always-create-state-file-in-signal-h.patch +++ b/0902-journald-server-always-create-state-file-in-signal-h.patch @@ -1,4 +1,4 @@ -From 47cc8f7e1d153e576f146d309b4043739997a673 Mon Sep 17 00:00:00 2001 +From 0491902d0eff9f4480ce873decc5dd29e5e189d7 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 13 Mar 2023 14:22:28 +0100 Subject: [PATCH] journald-server: always create state file in signal handler @@ -8,7 +8,7 @@ nothing has really happened. RHEL-only -Resolves: #2174645 +Resolves: #2176892 --- src/journal/journald-server.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/0903-journald-server-move-relinquish-code-into-function.patch b/0903-journald-server-move-relinquish-code-into-function.patch index 46f057d..8536ff8 100644 --- a/0903-journald-server-move-relinquish-code-into-function.patch +++ b/0903-journald-server-move-relinquish-code-into-function.patch @@ -1,4 +1,4 @@ -From 7a7b0c4ec7a5595a44d9c70d8270b0724a8b8c45 Mon Sep 17 00:00:00 2001 +From 62c8e07498c9dd13aa79371fc169bb51652ef3a9 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 13 Mar 2023 14:31:38 +0100 Subject: [PATCH] journald-server: move relinquish code into function @@ -7,7 +7,7 @@ No functional change, just refactoring. RHEL-only -Related: #2174645 +Related: #2176892 --- src/journal/journald-server.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/0904-journald-server-always-touch-state-file-in-signal-ha.patch b/0904-journald-server-always-touch-state-file-in-signal-ha.patch index 40267b7..b6b9436 100644 --- a/0904-journald-server-always-touch-state-file-in-signal-ha.patch +++ b/0904-journald-server-always-touch-state-file-in-signal-ha.patch @@ -1,4 +1,4 @@ -From 980add7d84084a474c6c604c0670743c2d1e624c Mon Sep 17 00:00:00 2001 +From 05a06e34ac8a38c1cff2a08ba071386141e0b78d Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 13 Mar 2023 14:32:20 +0100 Subject: [PATCH] journald-server: always touch state file in signal handler @@ -8,7 +8,7 @@ even if nothing has really happened. RHEL-only -Related: #2174645 +Related: #2176892 --- src/journal/journald-server.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/0905-test-make-TEST-35-LOGIN-stable-again.patch b/0905-test-make-TEST-35-LOGIN-stable-again.patch new file mode 100644 index 0000000..45fa87d --- /dev/null +++ b/0905-test-make-TEST-35-LOGIN-stable-again.patch @@ -0,0 +1,299 @@ +From 96e69cb655c703d5312c4aa44912e6ce90b4f76f Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Wed, 29 Mar 2023 22:38:55 +0200 +Subject: [PATCH] test: make TEST-35-LOGIN stable again + +The expect stuff was anything but expected, so let's just backport +the upstream test case and tweak it a bit to account for the missing +parts in our downstream testing infrastructure. + +Follow-up to 638c2418e7. +Related: #2179309 +rhel-only +--- + test/TEST-35-LOGIN/testsuite.sh | 225 ++++++++++++++++++++++++-------- + test/test-functions | 2 +- + 2 files changed, 175 insertions(+), 52 deletions(-) + +diff --git a/test/TEST-35-LOGIN/testsuite.sh b/test/TEST-35-LOGIN/testsuite.sh +index e4d72beb74..149b2354a1 100755 +--- a/test/TEST-35-LOGIN/testsuite.sh ++++ b/test/TEST-35-LOGIN/testsuite.sh +@@ -3,6 +3,141 @@ + set -eux + set -o pipefail + ++cleanup_test_user() ( ++ set +ex ++ ++ pkill -u "$(id -u logind-test-user)" ++ sleep 1 ++ pkill -KILL -u "$(id -u logind-test-user)" ++ userdel -r logind-test-user ++ ++ return 0 ++) ++ ++setup_test_user() { ++ mkdir -p /var/spool/cron /var/spool/mail /var/run/console ++ useradd -m -s /bin/bash logind-test-user ++ trap cleanup_test_user EXIT ++} ++ ++test_enable_debug() { ++ mkdir -p /run/systemd/system/systemd-logind.service.d ++ cat >/run/systemd/system/systemd-logind.service.d/debug.conf <&2 ++ return 1 ++ fi ++ ++ seat=$(loginctl --no-legend | grep 'logind-test-user *seat' | awk '{ print $4 }') ++ if [[ -z "$seat" ]]; then ++ echo "no seat found for user logind-test-user" >&2 ++ return 1 ++ fi ++ ++ session=$(loginctl --no-legend | awk '$3 == "logind-test-user" { print $1 }') ++ if [[ -z "$session" ]]; then ++ echo "no session found for user logind-test-user" >&2 ++ return 1 ++ fi ++ ++ if ! loginctl session-status "$session" | grep -q "Unit: session-${session}\.scope"; then ++ echo "cannot find scope unit for session $session" >&2 ++ return 1 ++ fi ++ ++ leader_pid=$(loginctl session-status "$session" | awk '$1 == "Leader:" { print $2 }') ++ if [[ -z "$leader_pid" ]]; then ++ echo "cannot found leader process for session $session" >&2 ++ return 1 ++ fi ++ ++ # cgroup v1: "1:name=systemd:/user.slice/..."; unified hierarchy: "0::/user.slice" ++ if ! grep -q -E '(name=systemd|^0:):.*session.*scope' /proc/"$leader_pid"/cgroup; then ++ echo "FAIL: process $leader_pid is not in the session cgroup" >&2 ++ cat /proc/self/cgroup ++ return 1 ++ fi ++) ++ ++create_session() { ++ # login with the test user to start a session ++ mkdir -p /run/systemd/system/getty@tty2.service.d ++ cat >/run/systemd/system/getty@tty2.service.d/override.conf </dev/null ; then +- echo >&2 "expect not installed, skiping test ${FUNCNAME[0]}" +- return 0 +- fi ++ cleanup_session + +- setup_idle_action_lock +- trap teardown_idle_action_lock RETURN ++ return 0 ++) + +- if loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -q testuser ; then +- echo >&2 "Session of the \'testuser\' is already present." +- return 1 ++test_lock_idle_action() { ++ local ts ++ ++ if [[ ! -c /dev/tty2 ]]; then ++ echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}." ++ return + fi + +- # IdleActionSec is set 1s but the accuracy of associated timer is 30s so we +- # need to sleep in worst case for 31s to make sure timer elapsed. We sleep +- # here for 35s to accomodate for any possible scheudling delays. +- cat > /tmp/test.exp <&2 "Session of the \'logind-test-user\' is already present." ++ exit 1 ++ fi + +- ts="$(date '+%H:%M:%S')" +- busctl --match "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='Lock'" monitor > dbus.log & ++ trap teardown_lock_idle_action RETURN + +- expect /tmp/test.exp & ++ create_session + +- # Sleep a bit to give expect time to spawn systemd-run before we check for +- # the presence of resulting session. +- sleep 2 +- if [ "$(loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -c testuser)" != 1 ] ; then +- echo >&2 "\'testuser\' is expected to have exactly one session running." +- return 1 +- fi ++ ts="$(date '+%H:%M:%S')" + +- wait %2 +- sleep 20 +- kill %1 ++ mkdir -p /run/systemd/logind.conf.d ++ cat >/run/systemd/logind.conf.d/idle-action-lock.conf <&2 "Too few 'Lock' D-Bus signal sent, expected at least 2." +- return 1 +- fi ++ timeout 35 bash -c "while [[ \"\$(journalctl -b -u systemd-logind.service --since=$ts | grep -c 'Sent message type=signal .* member=Lock')\" -lt 1 ]]; do sleep 1; done" ++ ++ # Wakeup ++ touch /dev/tty2 ++ ++ # Wait again ++ timeout 35 bash -c "while [[ \"\$(journalctl -b -u systemd-logind.service --since=$ts | grep -c 'Sent message type=signal .* member=Lock')\" -lt 2 ]]; do sleep 1; done" + +- journalctl -b -u systemd-logind.service --since="$ts" > logind.log +- if [ "$(grep -c 'System idle. Doing lock operation.' logind.log)" -lt 2 ]; then ++ if [[ "$(journalctl -b -u systemd-logind.service --since="$ts" | grep -c 'System idle. Doing lock operation.')" -lt 2 ]]; then + echo >&2 "System haven't entered idle state at least 2 times." +- return 1 ++ exit 1 + fi +- +- rm -f dbus.log logind.log + } + + : >/failed + ++setup_test_user ++test_enable_debug + test_lock_idle_action + + touch /testok +diff --git a/test/test-functions b/test/test-functions +index 9606a1b085..e5d4d28a5f 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -23,7 +23,7 @@ fi + + PATH_TO_INIT=$ROOTLIBDIR/systemd + +-BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint useradd userdel" ++BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint useradd userdel timeout" + DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find" + + STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))" diff --git a/0906-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch b/0906-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch new file mode 100644 index 0000000..ddb15e1 --- /dev/null +++ b/0906-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch @@ -0,0 +1,113 @@ +From c971d99ffc43df89ca4e15cd81f9e44f4139ba91 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 31 Aug 2020 19:37:13 +0200 +Subject: [PATCH] pager: set $LESSSECURE whenver we invoke a pager + +Some extra safety when invoked via "sudo". With this we address a +genuine design flaw of sudo, and we shouldn't need to deal with this. +But it's still a good idea to disable this surface given how exotic it +is. + +Prompted by #5666 + +(cherry picked from commit 612ebf6c913dd0e4197c44909cb3157f5c51a2f0) + +Related: #2175624 +--- + man/less-variables.xml | 8 ++++++++ + man/systemctl.xml | 1 + + man/systemd.xml | 2 ++ + src/basic/pager.c | 23 +++++++++++++++++++++-- + 4 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index a3faa38997..9dad4247da 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -36,5 +36,13 @@ + the invoking terminal is determined to be UTF-8 compatible). + + ++ ++ $SYSTEMD_LESSSECURE ++ ++ Takes a boolean argument. Overrides the $LESSSECURE environment ++ variable when invoking the pager, which controls the "secure" mode of less (which disables commands ++ such as | which allow to easily shell out to external command lines). By default ++ less secure mode is enabled, with this setting it may be disabled. ++ + + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index a71e6c7c4f..abc386e6fb 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -2010,6 +2010,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + ++ + + + +diff --git a/man/systemd.xml b/man/systemd.xml +index 17ab59beb5..66ae4d841d 100644 +--- a/man/systemd.xml ++++ b/man/systemd.xml +@@ -862,6 +862,8 @@ + + + ++ ++ + + $LISTEN_PID + $LISTEN_FDS +diff --git a/src/basic/pager.c b/src/basic/pager.c +index f241261119..4efb01c483 100644 +--- a/src/basic/pager.c ++++ b/src/basic/pager.c +@@ -11,6 +11,7 @@ + #include + + #include "copy.h" ++#include "env-util.h" + #include "fd-util.h" + #include "locale-util.h" + #include "log.h" +@@ -94,8 +95,7 @@ int pager_open(bool no_pager, bool jump_to_end) { + if (setenv("LESS", less_opts, 1) < 0) + _exit(EXIT_FAILURE); + +- /* Initialize a good charset for less. This is +- * particularly important if we output UTF-8 ++ /* Initialize a good charset for less. This is particularly important if we output UTF-8 + * characters. */ + less_charset = getenv("SYSTEMD_LESSCHARSET"); + if (!less_charset && is_locale_utf8()) +@@ -104,6 +104,25 @@ int pager_open(bool no_pager, bool jump_to_end) { + setenv("LESSCHARSET", less_charset, 1) < 0) + _exit(EXIT_FAILURE); + ++ /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out ++ * privileged stuff. */ ++ r = getenv_bool("SYSTEMD_LESSSECURE"); ++ if (r == 0) { /* Remove env var if off */ ++ if (unsetenv("LESSSECURE") < 0) { ++ log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ } else { ++ /* Set env var otherwise */ ++ if (r < 0) ++ log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m"); ++ ++ if (setenv("LESSSECURE", "1", 1) < 0) { ++ log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ } ++ + if (pager) { + execlp(pager, pager, NULL); + execl("/bin/sh", "sh", "-c", pager, NULL); diff --git a/0907-test-login-always-test-sd_pid_get_owner_uid-moderniz.patch b/0907-test-login-always-test-sd_pid_get_owner_uid-moderniz.patch new file mode 100644 index 0000000..c68d02d --- /dev/null +++ b/0907-test-login-always-test-sd_pid_get_owner_uid-moderniz.patch @@ -0,0 +1,264 @@ +From a45636228c7000aef000e45d9853585e51bfb9ef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 12 Oct 2020 18:57:32 +0200 +Subject: [PATCH] test-login: always test sd_pid_get_owner_uid(), modernize + +A long time some function only worked when in a session, and the test +didn't execute them when sd_pid_get_session() failed. Let's always call +them to increase coverage. + +While at it, let's test for ==0 not >=0 where we don't expect the function +to return anything except 0 or error. + +(cherry picked from commit 1b5b507cd2d1d7a2b053151abb548475ad9c5c3b) + +Related: #2175624 +--- + src/libsystemd/sd-login/test-login.c | 132 ++++++++++++++------------- + 1 file changed, 71 insertions(+), 61 deletions(-) + +diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c +index ccb1905a46..60ef889ec0 100644 +--- a/src/libsystemd/sd-login/test-login.c ++++ b/src/libsystemd/sd-login/test-login.c +@@ -8,20 +8,22 @@ + #include "sd-login.h" + + #include "alloc-util.h" ++#include "errno-list.h" + #include "fd-util.h" + #include "format-util.h" + #include "log.h" + #include "string-util.h" + #include "strv.h" +-#include "util.h" ++#include "time-util.h" ++#include "user-util.h" + + static char* format_uids(char **buf, uid_t* uids, int count) { +- int pos = 0, k, inc; ++ int pos = 0, inc; + size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1; + + assert_se(*buf = malloc(size)); + +- for (k = 0; k < count; k++) { ++ for (int k = 0; k < count; k++) { + sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc); + pos += inc; + } +@@ -32,6 +34,10 @@ static char* format_uids(char **buf, uid_t* uids, int count) { + return *buf; + } + ++static const char *e(int r) { ++ return r == 0 ? "OK" : errno_to_name(r); ++} ++ + static void test_login(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_free_ char *pp = NULL, *qq = NULL, +@@ -41,65 +47,71 @@ static void test_login(void) { + *seat = NULL, *session = NULL, + *unit = NULL, *user_unit = NULL, *slice = NULL; + int r; +- uid_t u, u2; +- char *t, **seats, **sessions; ++ uid_t u, u2 = UID_INVALID; ++ char *t, **seats = NULL, **sessions = NULL; + + r = sd_pid_get_unit(0, &unit); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit)); ++ log_info("sd_pid_get_unit(0, …) → %s / \"%s\"", e(r), strnull(unit)); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_user_unit(0, &user_unit); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit)); ++ log_info("sd_pid_get_user_unit(0, …) → %s / \"%s\"", e(r), strnull(user_unit)); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_slice(0, &slice); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice)); ++ log_info("sd_pid_get_slice(0, …) → %s / \"%s\"", e(r), strnull(slice)); ++ assert_se(IN_SET(r, 0, -ENODATA)); ++ ++ r = sd_pid_get_owner_uid(0, &u2); ++ log_info("sd_pid_get_owner_uid(0, …) → %s / "UID_FMT, e(r), u2); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_session(0, &session); +- if (r < 0) { +- log_warning_errno(r, "sd_pid_get_session(0, …): %m"); +- if (r == -ENODATA) +- log_info("Seems we are not running in a session, skipping some tests."); +- } else { +- log_info("sd_pid_get_session(0, …) → \"%s\"", session); +- +- assert_se(sd_pid_get_owner_uid(0, &u2) == 0); +- log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2); +- +- assert_se(sd_pid_get_cgroup(0, &cgroup) == 0); +- log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup); +- +- r = sd_uid_get_display(u2, &display_session); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"", +- u2, strnull(display_session)); +- +- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); +- sd_peer_get_session(pair[0], &pp); +- sd_peer_get_session(pair[1], &qq); +- assert_se(streq_ptr(pp, qq)); +- +- r = sd_uid_get_sessions(u2, false, &sessions); ++ log_info("sd_pid_get_session(0, …) → %s / \"%s\"", e(r), strnull(session)); ++ ++ r = sd_pid_get_cgroup(0, &cgroup); ++ log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup)); ++ assert_se(r == 0); ++ ++ r = sd_uid_get_display(u2, &display_session); ++ log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session)); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else ++ assert_se(IN_SET(r, 0, -ENODATA)); ++ ++ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); ++ sd_peer_get_session(pair[0], &pp); ++ sd_peer_get_session(pair[1], &qq); ++ assert_se(streq_ptr(pp, qq)); ++ ++ r = sd_uid_get_sessions(u2, false, &sessions); ++ assert_se(t = strv_join(sessions, " ")); ++ log_info("sd_uid_get_sessions("UID_FMT", …) → %s \"%s\"", u2, e(r), t); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else { + assert_se(r >= 0); + assert_se(r == (int) strv_length(sessions)); +- assert_se(t = strv_join(sessions, " ")); +- strv_free(sessions); +- log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t); +- free(t); ++ } ++ sessions = strv_free(sessions); ++ free(t); + +- assert_se(r == sd_uid_get_sessions(u2, false, NULL)); ++ assert_se(r == sd_uid_get_sessions(u2, false, NULL)); + +- r = sd_uid_get_seats(u2, false, &seats); ++ r = sd_uid_get_seats(u2, false, &seats); ++ assert_se(t = strv_join(seats, " ")); ++ log_info("sd_uid_get_seats("UID_FMT", …) → %s \"%s\"", u2, e(r), t); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else { + assert_se(r >= 0); + assert_se(r == (int) strv_length(seats)); +- assert_se(t = strv_join(seats, " ")); +- strv_free(seats); +- log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t); +- free(t); +- +- assert_se(r == sd_uid_get_seats(u2, false, NULL)); + } ++ seats = strv_free(seats); ++ free(t); ++ ++ assert_se(r == sd_uid_get_seats(u2, false, NULL)); + + if (session) { + r = sd_session_is_active(session); +@@ -111,7 +123,7 @@ static void test_login(void) { + log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r)); + + r = sd_session_get_state(session, &state); +- assert_se(r >= 0); ++ assert_se(r == 0); + log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state); + + assert_se(sd_session_get_uid(session, &u) >= 0); +@@ -125,16 +137,16 @@ static void test_login(void) { + log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class); + + r = sd_session_get_display(session, &display); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display)); + + r = sd_session_get_remote_user(session, &remote_user); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_remote_user(\"%s\") → \"%s\"", + session, strna(remote_user)); + + r = sd_session_get_remote_host(session, &remote_host); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_remote_host(\"%s\") → \"%s\"", + session, strna(remote_host)); + +@@ -160,7 +172,7 @@ static void test_login(void) { + assert_se(r == -ENODATA); + } + +- assert_se(sd_uid_get_state(u, &state2) >= 0); ++ assert_se(sd_uid_get_state(u, &state2) == 0); + log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2); + } + +@@ -172,11 +184,11 @@ static void test_login(void) { + assert_se(sd_uid_is_on_seat(u, 0, seat) > 0); + + r = sd_seat_get_active(seat, &session2, &u2); +- assert_se(r >= 0); ++ assert_se(r == 0); + log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2); + + r = sd_uid_is_on_seat(u, 1, seat); +- assert_se(r >= 0); ++ assert_se(IN_SET(r, 0, 1)); + assert_se(!!r == streq(session, session2)); + + r = sd_seat_get_sessions(seat, &sessions, &uids, &n); +@@ -184,8 +196,8 @@ static void test_login(void) { + assert_se(r == (int) strv_length(sessions)); + assert_se(t = strv_join(sessions, " ")); + strv_free(sessions); +- log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}", +- seat, r, t, n, format_uids(&buf, uids, n)); ++ log_info("sd_seat_get_sessions(\"%s\", …) → %s, \"%s\", [%u] {%s}", ++ seat, e(r), t, n, format_uids(&buf, uids, n)); + free(t); + + assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r); +@@ -203,7 +215,7 @@ static void test_login(void) { + + r = sd_seat_get_active(NULL, &t, NULL); + assert_se(IN_SET(r, 0, -ENODATA)); +- log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t)); ++ log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t)); + free(t); + + r = sd_get_sessions(&sessions); +@@ -243,13 +255,11 @@ static void test_login(void) { + + static void test_monitor(void) { + sd_login_monitor *m = NULL; +- unsigned n; + int r; + +- r = sd_login_monitor_new("session", &m); +- assert_se(r >= 0); ++ assert_se(sd_login_monitor_new("session", &m) == 0); + +- for (n = 0; n < 5; n++) { ++ for (unsigned n = 0; n < 5; n++) { + struct pollfd pollfd = {}; + usec_t timeout, nw; + diff --git a/0908-pager-make-pager-secure-when-under-euid-is-changed-o.patch b/0908-pager-make-pager-secure-when-under-euid-is-changed-o.patch new file mode 100644 index 0000000..101d8c4 --- /dev/null +++ b/0908-pager-make-pager-secure-when-under-euid-is-changed-o.patch @@ -0,0 +1,198 @@ +From 7955f053c498a70616ac6c4d57c0fd47dfa8e5ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 7 Oct 2020 11:15:05 +0200 +Subject: [PATCH] pager: make pager secure when under euid is changed or + explicitly requested + +The variable is renamed to SYSTEMD_PAGERSECURE (because it's not just about +less now), and we automatically enable secure mode in certain cases, but not +otherwise. + +This approach is more nuanced, but should provide a better experience for +users: + +- Previusly we would set LESSSECURE=1 and trust the pager to make use of + it. But this has an effect only on less. We need to not start pagers which + are insecure when in secure mode. In particular more is like that and is a + very popular pager. + +- We don't enable secure mode always, which means that those other pagers can + reasonably used. + +- We do the right thing by default, but the user has ultimate control by + setting SYSTEMD_PAGERSECURE. + +Fixes #5666. + +v2: +- also check $PKEXEC_UID + +v3: +- use 'sd_pid_get_owner_uid() != geteuid()' as the condition + +(cherry picked from commit 0a42426d797406b4b01a0d9c13bb759c2629d108) + +Resolves: #2175624 +--- + man/less-variables.xml | 28 ++++++++++++++--- + meson.build | 3 +- + src/basic/pager.c | 69 +++++++++++++++++++++++++++--------------- + 3 files changed, 69 insertions(+), 31 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index 9dad4247da..5f3a53c8dd 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -37,12 +37,30 @@ + + + +- $SYSTEMD_LESSSECURE ++ $SYSTEMD_PAGERSECURE + +- Takes a boolean argument. Overrides the $LESSSECURE environment +- variable when invoking the pager, which controls the "secure" mode of less (which disables commands +- such as | which allow to easily shell out to external command lines). By default +- less secure mode is enabled, with this setting it may be disabled. ++ Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if ++ 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. ++ 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 ++ $SYSTEMD_PAGERSECURE is not set at all, pagers which are not known to implement ++ secure mode will not be used. (Currently only ++ less1 implements ++ secure mode.) ++ ++ Note: when commands are invoked with elevated privileges, for example under sudo8 or ++ pkexec1, care ++ must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the ++ pager may be enabled automatically as describe above. Setting SYSTEMD_PAGERSECURE=0 ++ or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note ++ that if the $SYSTEMD_PAGER or $PAGER variables are to be ++ honoured, $SYSTEMD_PAGERSECURE must be set too. It might be reasonable to completly ++ disable the pager using instead. + + + +diff --git a/meson.build b/meson.build +index 673800a1a7..d986dd24ac 100644 +--- a/meson.build ++++ b/meson.build +@@ -1467,7 +1467,8 @@ test_dlopen = executable( + 'test-dlopen', + test_dlopen_c, + include_directories : includes, +- link_with : [libbasic], ++ link_with : [libsystemd_static, ++ libbasic], + dependencies : [libdl]) + + foreach tuple : [['myhostname', 'ENABLE_NSS_MYHOSTNAME'], +diff --git a/src/basic/pager.c b/src/basic/pager.c +index 4efb01c483..c7e101235d 100644 +--- a/src/basic/pager.c ++++ b/src/basic/pager.c +@@ -10,6 +10,8 @@ + #include + #include + ++#include "sd-login.h" ++ + #include "copy.h" + #include "env-util.h" + #include "fd-util.h" +@@ -79,7 +81,7 @@ int pager_open(bool no_pager, bool jump_to_end) { + if (r < 0) + return r; + if (r == 0) { +- const char* less_opts, *less_charset; ++ const char* less_opts, *less_charset, *exe; + + /* In the child start the pager */ + +@@ -105,39 +107,56 @@ int pager_open(bool no_pager, bool jump_to_end) { + _exit(EXIT_FAILURE); + + /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out +- * privileged stuff. */ +- r = getenv_bool("SYSTEMD_LESSSECURE"); +- if (r == 0) { /* Remove env var if off */ +- if (unsetenv("LESSSECURE") < 0) { +- log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m"); +- _exit(EXIT_FAILURE); +- } +- } else { +- /* Set env var otherwise */ ++ * privileged stuff. If the user set $SYSTEMD_PAGERSECURE, trust their configuration of the ++ * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE ++ * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we ++ * 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_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m"); ++ 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) { ++ log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m"); ++ use_secure_mode = true; ++ } + +- if (setenv("LESSSECURE", "1", 1) < 0) { +- log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m"); +- _exit(EXIT_FAILURE); +- } ++ /* We generally always set variables used by less, even if we end up using a different pager. ++ * They shouldn't hurt in any case, and ideally other pagers would look at them too. */ ++ if (use_secure_mode) ++ r = setenv("LESSSECURE", "1", 1); ++ else ++ r = unsetenv("LESSSECURE"); ++ if (r < 0) { ++ log_error_errno(errno, "Failed to adjust environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); + } + +- if (pager) { ++ if (trust_pager && pager) { /* The pager config might be set globally, and we cannot ++ * know if the user adjusted it to be appropriate for the ++ * secure mode. Thus, start the pager specified through ++ * envvars only when $SYSTEMD_PAGERSECURE was explicitly set ++ * as well. */ + execlp(pager, pager, NULL); + execl("/bin/sh", "sh", "-c", pager, NULL); + } + +- /* Debian's alternatives command for pagers is +- * called 'pager'. Note that we do not call +- * sensible-pagers here, since that is just a +- * shell script that implements a logic that +- * is similar to this one anyway, but is +- * Debian-specific. */ +- execlp("pager", "pager", NULL); ++ /* Debian's alternatives command for pagers is called 'pager'. Note that we do not call ++ * sensible-pagers here, since that is just a shell script that implements a logic that is ++ * similar to this one anyway, but is Debian-specific. */ ++ FOREACH_STRING(exe, "pager", "less", "more") { ++ /* Only less implements secure mode right now. */ ++ if (use_secure_mode && !streq(exe, "less")) ++ continue; + +- execlp("less", "less", NULL); +- execlp("more", "more", NULL); ++ execlp(exe, exe, NULL); ++ } + + pager_fallback(); + /* not reached */ diff --git a/0909-ci-trigger-differential-shellcheck-workflow-on-push.patch b/0909-ci-trigger-differential-shellcheck-workflow-on-push.patch new file mode 100644 index 0000000..4845dee --- /dev/null +++ b/0909-ci-trigger-differential-shellcheck-workflow-on-push.patch @@ -0,0 +1,49 @@ +From c4c9126b1d64fbe77ef1a74b464646711ced8f83 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Thu, 30 Mar 2023 17:16:44 +0200 +Subject: [PATCH] ci: trigger differential-shellcheck workflow on push + +Fixes: redhat-plumbers-in-action/differential-shellcheck#215 + +rhel-only + +Related: #2179309 +--- + .github/workflows/differential-shellcheck.yml | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml +index 4399f0bc64..19634c07b3 100644 +--- a/.github/workflows/differential-shellcheck.yml ++++ b/.github/workflows/differential-shellcheck.yml +@@ -3,9 +3,13 @@ + + name: Differential ShellCheck + on: ++ push: ++ branches: ++ - main ++ - rhel-8.*.0 + pull_request: + branches: +- - master ++ - main + - rhel-8.*.0 + + permissions: +@@ -18,7 +22,6 @@ jobs: + + permissions: + security-events: write +- pull-requests: write + + steps: + - name: Repository checkout +@@ -27,6 +30,6 @@ jobs: + fetch-depth: 0 + + - name: Differential ShellCheck +- uses: redhat-plumbers-in-action/differential-shellcheck@v3 ++ uses: redhat-plumbers-in-action/differential-shellcheck@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/0910-ci-codeql-master-main.patch b/0910-ci-codeql-master-main.patch new file mode 100644 index 0000000..edd131e --- /dev/null +++ b/0910-ci-codeql-master-main.patch @@ -0,0 +1,34 @@ +From 5e5c1425db0982c9d5e5d51e164895aa780f76b2 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Thu, 30 Mar 2023 17:18:17 +0200 +Subject: [PATCH] ci: codeql `master` -> `main` + +rhel-only + +Related: #2179309 +--- + .github/workflows/codeql.yml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml +index c5426d5686..cc4fcf4754 100644 +--- a/.github/workflows/codeql.yml ++++ b/.github/workflows/codeql.yml +@@ -7,7 +7,7 @@ name: "CodeQL" + on: + pull_request: + branches: +- - master ++ - main + - rhel-* + paths: + - '**/meson.build' +@@ -17,7 +17,7 @@ on: + - 'tools/**' + push: + branches: +- - master ++ - main + - rhel-* + + permissions: diff --git a/0911-test-ignore-ENOMEDIUM-error-from-sd_pid_get_cgroup.patch b/0911-test-ignore-ENOMEDIUM-error-from-sd_pid_get_cgroup.patch new file mode 100644 index 0000000..6d35361 --- /dev/null +++ b/0911-test-ignore-ENOMEDIUM-error-from-sd_pid_get_cgroup.patch @@ -0,0 +1,30 @@ +From d9e2735b88513e3b3af9ab468f4d2ba0f6bec64d Mon Sep 17 00:00:00 2001 +From: Dan Streetman +Date: Fri, 23 Oct 2020 15:50:28 -0400 +Subject: [PATCH] test: ignore ENOMEDIUM error from sd_pid_get_cgroup() + +Ubuntu builds on the Launchpad infrastructure run inside a chroot that does +not have the sysfs cgroup dirs mounted, so this call will return ENOMEDIUM +from cg_unified_cached() during the build-time testing, for example when +building the package in a Launchpad PPA. + +(cherry picked from commit 352ab9d74049b4ac694fdba1a6e67339f12ded93) + +Resolves: #2175622 +--- + src/libsystemd/sd-login/test-login.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c +index 60ef889ec0..d24a04ccc8 100644 +--- a/src/libsystemd/sd-login/test-login.c ++++ b/src/libsystemd/sd-login/test-login.c +@@ -71,7 +71,7 @@ static void test_login(void) { + + r = sd_pid_get_cgroup(0, &cgroup); + log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup)); +- assert_se(r == 0); ++ assert_se(IN_SET(r, 0, -ENOMEDIUM)); + + r = sd_uid_get_display(u2, &display_session); + log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session)); diff --git a/systemd.spec b/systemd.spec index da5b57f..9f74f77 100644 --- a/systemd.spec +++ b/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 74%{?dist} +Release: 75%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -954,6 +954,13 @@ Patch0901: 0901-man-document-the-new-_LINE_BREAK-type.patch Patch0902: 0902-journald-server-always-create-state-file-in-signal-h.patch Patch0903: 0903-journald-server-move-relinquish-code-into-function.patch Patch0904: 0904-journald-server-always-touch-state-file-in-signal-ha.patch +Patch0905: 0905-test-make-TEST-35-LOGIN-stable-again.patch +Patch0906: 0906-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch +Patch0907: 0907-test-login-always-test-sd_pid_get_owner_uid-moderniz.patch +Patch0908: 0908-pager-make-pager-secure-when-under-euid-is-changed-o.patch +Patch0909: 0909-ci-trigger-differential-shellcheck-workflow-on-push.patch +Patch0910: 0910-ci-codeql-master-main.patch +Patch0911: 0911-test-ignore-ENOMEDIUM-error-from-sd_pid_get_cgroup.patch %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 @@ -1584,6 +1591,18 @@ fi %files tests -f .file-list-tests %changelog +* Tue Apr 18 2023 systemd maintenance team - 239-75 +- journald-server: always create state file in signal handler (#2176892) +- journald-server: move relinquish code into function (#2176892) +- journald-server: always touch state file in signal handler (#2176892) +- test: make TEST-35-LOGIN stable again (#2179309) +- pager: set $LESSSECURE whenver we invoke a pager (#2175624) +- test-login: always test sd_pid_get_owner_uid(), modernize (#2175624) +- pager: make pager secure when under euid is changed or explicitly requested (#2175624) +- ci: trigger differential-shellcheck workflow on push (#2179309) +- ci: codeql `master` -> `main` (#2179309) +- test: ignore ENOMEDIUM error from sd_pid_get_cgroup() (#2175622) + * Tue Mar 14 2023 systemd maintenance team - 239-74 - journald-server: always create state file in signal handler (#2174645) - journald-server: move relinquish code into function (#2174645)